1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
next.js/packages/next/export/worker.js
Benjamin Kniffler e6c3686629 multi-threaded export with nice progress indication (#5870)
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.
2018-12-12 13:59:11 +01:00

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 })
}
}
)