abe8b1e0a8
This PR adds the optional `limit` parameter on String.prototype.split uses. > If provided, splits the string at each occurrence of the specified separator, but stops when limit entries have been placed in the array. Any leftover text is not included in the array at all. [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#syntax) While the performance gain may not be significant for small texts, it can be huge for large ones. I made a benchmark on the following repository : https://github.com/Yovach/benchmark-nodejs On my machine, I get the following results: `node index.js` > normal 1: 570.092ms > normal 50: 2.284s > normal 100: 3.543s `node index-optimized.js` > optmized 1: 644.301ms > optmized 50: 929.39ms > optmized 100: 1.020s The "benchmarks" numbers are : - "lorem-1" file contains 1 paragraph of "lorem ipsum" - "lorem-50" file contains 50 paragraphes of "lorem ipsum" - "lorem-100" file contains 100 paragraphes of "lorem ipsum"
128 lines
3.6 KiB
TypeScript
128 lines
3.6 KiB
TypeScript
import spawn from 'cross-spawn'
|
|
import { Span } from 'next/src/trace'
|
|
import { NextInstance } from './base'
|
|
import { getTurbopackFlag } from '../turbo'
|
|
import stripAnsi from 'strip-ansi'
|
|
|
|
export class NextDevInstance extends NextInstance {
|
|
private _cliOutput: string = ''
|
|
|
|
public get buildId() {
|
|
return 'development'
|
|
}
|
|
|
|
public async setup(parentSpan: Span) {
|
|
await super.createTestDir({ parentSpan })
|
|
}
|
|
|
|
public get cliOutput() {
|
|
return this._cliOutput || ''
|
|
}
|
|
|
|
public async start(useDirArg: boolean = false) {
|
|
if (this.childProcess) {
|
|
throw new Error('next already started')
|
|
}
|
|
|
|
const useTurbo =
|
|
!process.env.TEST_WASM &&
|
|
((this as any).turbo || (this as any).experimentalTurbo)
|
|
|
|
let startArgs = [
|
|
'yarn',
|
|
'next',
|
|
useTurbo ? getTurbopackFlag() : undefined,
|
|
useDirArg && this.testDir,
|
|
].filter(Boolean) as string[]
|
|
|
|
if (this.startCommand) {
|
|
startArgs = this.startCommand.split(' ')
|
|
}
|
|
|
|
if (process.env.NEXT_SKIP_ISOLATE) {
|
|
// without isolation yarn can't be used and pnpm must be used instead
|
|
if (startArgs[0] === 'yarn') {
|
|
startArgs[0] = 'pnpm'
|
|
}
|
|
}
|
|
|
|
console.log('running', startArgs.join(' '))
|
|
await new Promise<void>((resolve, reject) => {
|
|
try {
|
|
this.childProcess = spawn(startArgs[0], startArgs.slice(1), {
|
|
cwd: useDirArg ? process.cwd() : this.testDir,
|
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
shell: false,
|
|
env: {
|
|
...process.env,
|
|
...this.env,
|
|
NODE_ENV: this.env.NODE_ENV || ('' as any),
|
|
PORT: this.forcedPort || '0',
|
|
__NEXT_TEST_MODE: 'e2e',
|
|
__NEXT_TEST_WITH_DEVTOOL: '1',
|
|
},
|
|
})
|
|
|
|
this._cliOutput = ''
|
|
|
|
this.childProcess.stdout.on('data', (chunk) => {
|
|
const msg = chunk.toString()
|
|
if (!process.env.CI) process.stdout.write(chunk)
|
|
this._cliOutput += msg
|
|
this.emit('stdout', [msg])
|
|
})
|
|
this.childProcess.stderr.on('data', (chunk) => {
|
|
const msg = chunk.toString()
|
|
if (!process.env.CI) process.stderr.write(chunk)
|
|
this._cliOutput += msg
|
|
this.emit('stderr', [msg])
|
|
})
|
|
|
|
this.childProcess.on('close', (code, signal) => {
|
|
if (this.isStopping) return
|
|
if (code || signal) {
|
|
require('console').error(
|
|
`next dev exited unexpectedly with code/signal ${code || signal}`
|
|
)
|
|
}
|
|
})
|
|
|
|
const readyCb = (msg) => {
|
|
const resolveServer = () => {
|
|
try {
|
|
this._parsedUrl = new URL(this._url)
|
|
} catch (err) {
|
|
reject({
|
|
err,
|
|
msg,
|
|
})
|
|
}
|
|
// server might reload so we keep listening
|
|
resolve()
|
|
}
|
|
|
|
const colorStrippedMsg = stripAnsi(msg)
|
|
if (colorStrippedMsg.includes('- Local:')) {
|
|
this._url = msg
|
|
.split('\n')
|
|
.find((line) => line.includes('- Local:'))
|
|
.split(/\s*- Local:/)
|
|
.pop()
|
|
.trim()
|
|
resolveServer()
|
|
} else if (
|
|
msg.includes('started server on') &&
|
|
msg.includes('url:')
|
|
) {
|
|
this._url = msg.split('url: ').pop().split(/\s/, 1)[0].trim()
|
|
resolveServer()
|
|
}
|
|
}
|
|
this.on('stdout', readyCb)
|
|
} catch (err) {
|
|
require('console').error(`Failed to run ${startArgs.join(' ')}`, err)
|
|
setTimeout(() => process.exit(1), 0)
|
|
}
|
|
})
|
|
}
|
|
}
|