From e49424fb6bb8f068ea03110e7e19d4f6cf19802e Mon Sep 17 00:00:00 2001 From: ausir Date: Mon, 22 May 2017 03:42:42 +0800 Subject: [PATCH] generate with child process --- lib/generate.js | 120 +++++++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 46 deletions(-) diff --git a/lib/generate.js b/lib/generate.js index f8053455ac..62dc708a95 100644 --- a/lib/generate.js +++ b/lib/generate.js @@ -11,6 +11,8 @@ const copy = pify(fs.copy) const remove = pify(fs.remove) const writeFile = pify(fs.writeFile) const mkdirp = pify(fs.mkdirp) +const numWorkers = require('os').cpus().length +const childProcess = require('child_process') const defaults = { dir: 'dist', @@ -39,6 +41,7 @@ const defaults = { } export default async function () { + const child = process.argv[3] const s = Date.now() let errors = [] /* @@ -49,25 +52,27 @@ export default async function () { var srcBuiltPath = resolve(this.dir, '.nuxt', 'dist') var distPath = resolve(this.dir, this.options.generate.dir) var distNuxtPath = join(distPath, (isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath)) - /* - ** Launch build process - */ - await this.build() - /* - ** Clean destination folder - */ - try { - await remove(distPath) - debug('Destination folder cleaned') - } catch (e) {} - /* - ** Copy static and built files - */ - if (fs.existsSync(srcStaticPath)) { - await copy(srcStaticPath, distPath) + if (!child) { + /* + ** Launch build process + */ + await this.build() + /* + ** Clean destination folder + */ + try { + await remove(distPath) + debug('Destination folder cleaned') + } catch (e) {} + /* + ** Copy static and built files + */ + if (fs.existsSync(srcStaticPath)) { + await copy(srcStaticPath, distPath) + } + await copy(srcBuiltPath, distNuxtPath) + debug('Static & build files copied') } - await copy(srcBuiltPath, distNuxtPath) - debug('Static & build files copied') if (this.options.router.mode !== 'hash') { // Resolve config.generate.routes promises before generating the routes try { @@ -82,6 +87,7 @@ export default async function () { ** Generate html files from routes */ generateRoutes.forEach((route) => { + this.routes || (this.routes = []) if (this.routes.indexOf(route) < 0) { this.routes.push(route) } @@ -91,37 +97,59 @@ export default async function () { ** Generate only index.html for router.mode = 'hash' */ let routes = (this.options.router.mode === 'hash') ? ['/'] : this.routes - while (routes.length) { - let n = 0 - await Promise.all(routes.splice(0, 500).map(async (route) => { - await waitFor(n++ * this.options.generate.interval) - let html - try { - const res = await this.renderRoute(route, { _generate: true }) - html = res.html - if (res.error) { - errors.push({ type: 'handled', route, error: res.error }) - } - } catch (err) { - /* istanbul ignore next */ - errors.push({ type: 'unhandled', route, error: err }) - } - if (this.options.generate.minify) { + + const prmiseArray = [] + if (!child) { + const workers = routes.length < numWorkers ? routes.length : numWorkers + for (let i = 0; i < workers; i++) { + prmiseArray.push(new Promise((resolve) => { + childProcess.exec(`node ./bin/nuxt generate . child-${i}`, (err, stdout, stderr) => { + if (err) { + debug(`child-${i} has error ${err}`) + } else { + debug(`child-${i} generate success`) + } + resolve(`child-${i} generate finish`) + }) + })) + } + } else { + const start = parseInt(child.split('-')[1]) + const quantity = Math.ceil(routes.length / (numWorkers - 1)) + routes = routes.splice(start * quantity, quantity) + while (routes.length) { + let n = 0 + await Promise.all(routes.splice(0, 500).map(async (route) => { + await waitFor(n++ * this.options.generate.interval) + let html try { - html = minify(html, this.options.generate.minify) - } catch (err) /* istanbul ignore next */ { - const minifyErr = new Error(`HTML minification failed. Make sure the route generates valid HTML. Failed HTML:\n ${html}`) - errors.push({ type: 'unhandled', route, error: minifyErr }) + const res = await this.renderRoute(route, { _generate: true }) + html = res.html + if (res.error) { + errors.push({ type: 'handled', route, error: res.error }) + } + } catch (err) { + /* istanbul ignore next */ + errors.push({ type: 'unhandled', route, error: err }) } - } - let path = join(route, sep, 'index.html') // /about -> /about/index.html - debug('Generate file: ' + path) - path = join(distPath, path) - // Make sure the sub folders are created - await mkdirp(dirname(path)) - await writeFile(path, html, 'utf8') - })) + if (this.options.generate.minify) { + try { + html = minify(html, this.options.generate.minify) + } catch (err) /* istanbul ignore next */ { + const minifyErr = new Error(`HTML minification failed. Make sure the route generates valid HTML. Failed HTML:\n ${html}`) + errors.push({ type: 'unhandled', route, error: minifyErr }) + } + } + let path = join(route, sep, 'index.html') // /about -> /about/index.html + debug('Generate file: ' + path) + path = join(distPath, path) + // Make sure the sub folders are created + await mkdirp(dirname(path)) + await writeFile(path, html, 'utf8') + })) + } } + await Promise.all(prmiseArray) // Add .nojekyll file to let Github Pages add the _nuxt/ folder // https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/ const nojekyllPath = resolve(distPath, '.nojekyll')