mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
e6c3686629
This PR will - allow nextjs export to use all available CPU cores for rendering & writing pages by using child_process - make use of async-sema to allow each thread to concurrently write multiple paths - show a fancy progress bar while processing pages (with non-TTY fallback for CI web consoles) The performance gain for my MacBook with 4 CPU cores went from ~25 pages per second to ~75 pages per second. Beefy CI machines with lots of cores should profit even more.
60 lines
1.7 KiB
JavaScript
60 lines
1.7 KiB
JavaScript
global.__NEXT_DATA__ = {
|
|
nextExport: true
|
|
}
|
|
|
|
const { extname, join, dirname, sep } = require('path')
|
|
const mkdirp = require('mkdirp-then')
|
|
const { renderToHTML } = require('next-server/dist/server/render')
|
|
const { writeFile } = require('fs')
|
|
const Sema = require('async-sema')
|
|
|
|
process.on(
|
|
'message',
|
|
async ({
|
|
exportPaths,
|
|
exportPathMap,
|
|
outDir,
|
|
renderOpts,
|
|
concurrency
|
|
}) => {
|
|
const sema = new Sema(concurrency, { capacity: exportPaths.length })
|
|
try {
|
|
const work = async path => {
|
|
await sema.acquire()
|
|
const { page, query = {} } = exportPathMap[path]
|
|
const req = { url: path }
|
|
const res = {}
|
|
|
|
let htmlFilename = `${path}${sep}index.html`
|
|
if (extname(path) !== '') {
|
|
// If the path has an extension, use that as the filename instead
|
|
htmlFilename = path
|
|
} else if (path === '/') {
|
|
// If the path is the root, just use index.html
|
|
htmlFilename = 'index.html'
|
|
}
|
|
const baseDir = join(outDir, dirname(htmlFilename))
|
|
const htmlFilepath = join(outDir, htmlFilename)
|
|
|
|
await mkdirp(baseDir)
|
|
const html = await renderToHTML(req, res, page, query, renderOpts)
|
|
await new Promise((resolve, reject) =>
|
|
writeFile(
|
|
htmlFilepath,
|
|
html,
|
|
'utf8',
|
|
err => (err ? reject(err) : resolve())
|
|
)
|
|
)
|
|
process.send({ type: 'progress' })
|
|
sema.release()
|
|
}
|
|
await Promise.all(exportPaths.map(work))
|
|
process.send({ type: 'done' })
|
|
} catch (err) {
|
|
console.error(err)
|
|
process.send({ type: 'error', payload: err })
|
|
}
|
|
}
|
|
)
|