| | console.time('next-wall-time') |
| | |
| | |
| |
|
| | process.env.NODE_ENV = 'production' |
| |
|
| | |
| | process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = 'next' |
| |
|
| | let currentNode = null |
| |
|
| | let outliers = [] |
| |
|
| | const chalk = { |
| | yellow: (str) => `\x1b[33m${str}\x1b[0m`, |
| | green: (str) => `\x1b[32m${str}\x1b[0m`, |
| | } |
| |
|
| | if (process.env.LOG_REQUIRE) { |
| | const originalCompile = require('module').prototype._compile |
| |
|
| | require('module').prototype._compile = function (_content, filename) { |
| | let parent = currentNode |
| |
|
| | currentNode = { |
| | id: filename, |
| | selfDuration: 0, |
| | totalDuration: 0, |
| | children: [], |
| | } |
| |
|
| | const start = performance.now() |
| | const result = originalCompile.apply(this, arguments) |
| | const end = performance.now() |
| |
|
| | currentNode.totalDuration = end - start |
| | currentNode.selfDuration = currentNode.children.reduce( |
| | (acc, child) => acc - child.selfDuration, |
| | currentNode.totalDuration |
| | ) |
| |
|
| | parent?.children.push(currentNode) |
| | currentNode = parent || currentNode |
| | return result |
| | } |
| | } |
| |
|
| | function prettyPrint( |
| | node, |
| | distDir, |
| | prefix = '', |
| | isLast = false, |
| | isRoot = true |
| | ) { |
| | let duration = `${node.selfDuration.toFixed( |
| | 2 |
| | )}ms / ${node.totalDuration.toFixed(2)}ms` |
| |
|
| | if (node.selfDuration > 70) { |
| | duration = chalk.yellow(duration) |
| | outliers.push(node) |
| | } |
| |
|
| | let output = `${prefix}${isLast || isRoot ? '└─ ' : '├─ '}${chalk.green( |
| | path.relative(distDir, node.id) |
| | )} ${chalk.yellow(duration)}\n` |
| |
|
| | const childPrefix = `${prefix}${isRoot ? ' ' : isLast ? ' ' : '│ '}` |
| |
|
| | node.children.forEach((child, i) => { |
| | output += prettyPrint( |
| | child, |
| | node.id, |
| | childPrefix, |
| | i === node.children.length - 1, |
| | false |
| | ) |
| | }) |
| |
|
| | return output |
| | } |
| |
|
| | if (process.env.LOG_COMPILE) { |
| | const originalCompile = require('module').prototype._compile |
| | const currentDir = process.cwd() |
| | require('module').prototype._compile = function (content, filename) { |
| | const strippedFilename = filename.replace(currentDir, '') |
| | console.time(`Module '${strippedFilename}' compiled`) |
| | const result = originalCompile.apply(this, arguments) |
| | console.timeEnd(`Module '${strippedFilename}' compiled`) |
| | return result |
| | } |
| | } |
| |
|
| | const appDir = process.argv[2] |
| | const absoluteAppDir = require('path').resolve(appDir) |
| | process.chdir(absoluteAppDir) |
| |
|
| | let readFileCount = 0 |
| | let readFileSyncCount = 0 |
| |
|
| | if (process.env.LOG_READFILE) { |
| | const originalReadFile = require('fs').readFile |
| | const originalReadFileSync = require('fs').readFileSync |
| |
|
| | require('fs').readFile = function (path, options, callback) { |
| | readFileCount++ |
| | console.log(`readFile: ${require('path').relative(absoluteAppDir, path)}`) |
| | return originalReadFile.apply(this, arguments) |
| | } |
| |
|
| | require('fs').readFileSync = function (path, options) { |
| | readFileSyncCount++ |
| | console.log( |
| | `readFileSync: ${require('path').relative(absoluteAppDir, path)}` |
| | ) |
| | return originalReadFileSync.apply(this, arguments) |
| | } |
| | } |
| |
|
| | console.time('next-cold-start') |
| |
|
| | const NextServer = process.env.USE_BUNDLED_NEXT |
| | ? require('next/dist/compiled/next-server/server.runtime.prod').default |
| | : require('next/dist/server/next-server').default |
| |
|
| | if (process.env.LOG_READFILE) { |
| | console.log(`readFileCount: ${readFileCount + readFileSyncCount}`) |
| | } |
| |
|
| | const path = require('path') |
| |
|
| | const distDir = '.next' |
| |
|
| | const compiledConfig = require( |
| | path.join(absoluteAppDir, distDir, 'required-server-files.json') |
| | ).config |
| |
|
| | const nextServer = new NextServer({ |
| | conf: compiledConfig, |
| | dir: '.', |
| | distDir: distDir, |
| | minimalMode: true, |
| | customServer: false, |
| | }) |
| |
|
| | const requestHandler = nextServer.getRequestHandler() |
| |
|
| | require('http') |
| | .createServer((req, res) => { |
| | console.time('next-request') |
| | readFileCount = 0 |
| | readFileSyncCount = 0 |
| |
|
| | return requestHandler(req, res) |
| | .catch((err) => { |
| | console.error(err) |
| | res.statusCode = 500 |
| | res.end('Internal Server Error') |
| | }) |
| | .finally(() => { |
| | console.timeEnd('next-request') |
| | if (process.env.LOG_READFILE) { |
| | console.log(`readFileCount: ${readFileCount + readFileSyncCount}`) |
| | } |
| | }) |
| | }) |
| | .listen(3000, () => { |
| | console.timeEnd('next-cold-start') |
| | fetch('http://localhost:3000/' + (process.argv[3] || '')) |
| | .then((res) => res.text()) |
| | .catch((err) => { |
| | console.error(err) |
| | }) |
| | .finally(() => { |
| | console.timeEnd('next-wall-time') |
| | if (process.env.LOG_REQUIRE) { |
| | console.log( |
| | prettyPrint(currentNode, path.join(absoluteAppDir, distDir)) |
| | ) |
| | if (outliers.length > 0) { |
| | console.log('Outliers:') |
| | outliers.forEach((node) => { |
| | console.log( |
| | ` ${path.relative( |
| | path.join(absoluteAppDir, distDir), |
| | node.id |
| | )} ${node.selfDuration.toFixed( |
| | 2 |
| | )}ms / ${node.totalDuration.toFixed(2)}ms` |
| | ) |
| | }) |
| | } |
| | } |
| | require('process').exit(0) |
| | }) |
| | }) |
| |
|