/*!
|
* @nuxt/cli v2.15.8 (c) 2016-2021
|
* Released under the MIT License
|
* Repository: https://github.com/nuxt/nuxt.js
|
* Website: https://nuxtjs.org
|
*/
|
'use strict';
|
|
const utils = require('@nuxt/utils');
|
const consola = require('consola');
|
const index = require('./cli-index.js');
|
const path = require('path');
|
const upath = require('upath');
|
const fs = require('fs-extra');
|
const crc32 = require('crc/lib/crc32');
|
const globby = require('globby');
|
const destr = require('destr');
|
require('@nuxt/config');
|
require('exit');
|
require('chalk');
|
require('std-env');
|
require('wrap-ansi');
|
require('boxen');
|
require('minimist');
|
require('hable');
|
require('defu');
|
require('semver');
|
require('fs');
|
require('execa');
|
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
|
const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
const upath__default = /*#__PURE__*/_interopDefaultLegacy(upath);
|
const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
const crc32__default = /*#__PURE__*/_interopDefaultLegacy(crc32);
|
const globby__default = /*#__PURE__*/_interopDefaultLegacy(globby);
|
const destr__default = /*#__PURE__*/_interopDefaultLegacy(destr);
|
|
async function generate$1 (cmd) {
|
const nuxt = await getNuxt({ server: true }, cmd);
|
const generator = await cmd.getGenerator(nuxt);
|
|
await nuxt.server.listen(0);
|
const { errors } = await generator.generate({ build: false });
|
await nuxt.close();
|
if (cmd.argv['fail-on-error'] && errors.length > 0) {
|
throw new Error('Error generating pages, exiting with non-zero code')
|
}
|
}
|
|
async function ensureBuild (cmd) {
|
const nuxt = await getNuxt({ _build: true, server: false }, cmd);
|
const { options } = nuxt;
|
|
if (options.generate.cache === false || destr__default['default'](process.env.NUXT_BUILD) || cmd.argv['force-build']) {
|
const builder = await cmd.getBuilder(nuxt);
|
await builder.build();
|
await nuxt.close();
|
return
|
}
|
|
// Default build ignore files
|
const ignore = [
|
options.buildDir,
|
options.dir.static,
|
options.generate.dir,
|
'node_modules',
|
'.**/*',
|
'.*',
|
'README.md'
|
];
|
|
// Extend ignore
|
const { generate } = options;
|
if (typeof generate.cache.ignore === 'function') {
|
generate.cache.ignore = generate.cache.ignore(ignore);
|
} else if (Array.isArray(generate.cache.ignore)) {
|
generate.cache.ignore = generate.cache.ignore.concat(ignore);
|
}
|
await nuxt.callHook('generate:cache:ignore', generate.cache.ignore);
|
|
// Take a snapshot of current project
|
const snapshotOptions = {
|
rootDir: options.rootDir,
|
ignore: generate.cache.ignore.map(upath__default['default'].normalize),
|
globbyOptions: generate.cache.globbyOptions
|
};
|
|
const currentBuildSnapshot = await snapshot(snapshotOptions);
|
|
// Detect process.env usage in nuxt.config
|
const processEnv = {};
|
if (nuxt.options._nuxtConfigFile) {
|
const configSrc = await fs__default['default'].readFile(nuxt.options._nuxtConfigFile);
|
const envRegex = /process.env.(\w+)/g;
|
let match;
|
// eslint-disable-next-line no-cond-assign
|
while (match = envRegex.exec(configSrc)) {
|
processEnv[match[1]] = process.env[match[1]];
|
}
|
}
|
|
// Current build meta
|
const currentBuild = {
|
// @ts-ignore
|
nuxtVersion: nuxt.constructor.version,
|
ssr: nuxt.options.ssr,
|
target: nuxt.options.target,
|
snapshot: currentBuildSnapshot,
|
env: nuxt.options.env,
|
'process.env': processEnv
|
};
|
|
// Check if build can be skipped
|
const nuxtBuildFile = path__default['default'].resolve(nuxt.options.buildDir, 'build.json');
|
if (fs__default['default'].existsSync(nuxtBuildFile)) {
|
const previousBuild = destr__default['default'](fs__default['default'].readFileSync(nuxtBuildFile, 'utf-8')) || {};
|
|
// Quick diff
|
let needBuild = false;
|
for (const field of ['nuxtVersion', 'ssr', 'target', 'env', 'process.env']) {
|
if (JSON.stringify(previousBuild[field]) !== JSON.stringify(currentBuild[field])) {
|
needBuild = true;
|
consola__default['default'].info(`Doing webpack rebuild because ${field} changed`);
|
break
|
}
|
}
|
|
// Full snapshot diff
|
if (!needBuild) {
|
const changed = compareSnapshots(previousBuild.snapshot, currentBuild.snapshot);
|
if (!changed) {
|
consola__default['default'].success('Skipping webpack build as no changes detected');
|
return
|
} else {
|
consola__default['default'].info(`Doing webpack rebuild because ${changed} modified`);
|
}
|
}
|
}
|
|
// Webpack build
|
const builder = await cmd.getBuilder(nuxt);
|
await builder.build();
|
|
// Write build.json
|
fs__default['default'].writeFileSync(nuxtBuildFile, JSON.stringify(currentBuild, null, 2), 'utf-8');
|
|
await nuxt.close();
|
}
|
|
async function getNuxt (args, cmd) {
|
const config = await cmd.getNuxtConfig({ dev: false, ...args });
|
|
if (config.target === utils.TARGETS.static) {
|
config._export = true;
|
} else {
|
config._legacyGenerate = true;
|
}
|
config.buildDir = (config.static && config.static.cacheDir) || path__default['default'].resolve(config.rootDir, 'node_modules/.cache/nuxt');
|
config.build = config.build || {};
|
// https://github.com/nuxt/nuxt.js/issues/7390
|
config.build.parallel = false;
|
config.build.transpile = config.build.transpile || [];
|
if (!config.static || !config.static.cacheDir) {
|
config.build.transpile.push('.cache/nuxt');
|
}
|
|
const nuxt = await cmd.getNuxt(config);
|
|
return nuxt
|
}
|
|
function compareSnapshots (from, to) {
|
const allKeys = Array.from(new Set([
|
...Object.keys(from).sort(),
|
...Object.keys(to).sort()
|
]));
|
|
for (const key of allKeys) {
|
if (JSON.stringify(from[key]) !== JSON.stringify(to[key])) {
|
return key
|
}
|
}
|
|
return false
|
}
|
|
async function snapshot ({ globbyOptions, ignore, rootDir }) {
|
const snapshot = {};
|
|
const files = await globby__default['default']('**/*.*', {
|
...globbyOptions,
|
ignore,
|
cwd: rootDir,
|
absolute: true
|
});
|
|
await Promise.all(files.map(async (p) => {
|
const key = path.relative(rootDir, p);
|
try {
|
const fileContent = await fs__default['default'].readFile(p);
|
snapshot[key] = {
|
checksum: await crc32__default['default'](fileContent).toString(16)
|
};
|
} catch (e) {
|
// TODO: Check for other errors like permission denied
|
snapshot[key] = {
|
exists: false
|
};
|
}
|
}));
|
|
return snapshot
|
}
|
|
const generate = {
|
name: 'generate',
|
description: 'Generate a static web application (server-rendered)',
|
usage: 'generate <dir>',
|
options: {
|
...index.common,
|
...index.locking,
|
build: {
|
type: 'boolean',
|
default: true,
|
description: 'Only generate pages for dynamic routes, used for incremental builds. Generate has to be run once without this option before using it'
|
},
|
devtools: {
|
type: 'boolean',
|
default: false,
|
description: 'Enable Vue devtools',
|
prepare (cmd, options, argv) {
|
options.vue = options.vue || {};
|
options.vue.config = options.vue.config || {};
|
if (argv.devtools) {
|
options.vue.config.devtools = true;
|
}
|
}
|
},
|
quiet: {
|
alias: 'q',
|
type: 'boolean',
|
description: 'Disable output except for errors',
|
prepare (cmd, options, argv) {
|
// Silence output when using --quiet
|
options.build = options.build || {};
|
if (argv.quiet) {
|
options.build.quiet = true;
|
}
|
}
|
},
|
modern: {
|
...index.common.modern,
|
description: 'Generate app in modern build (modern mode can be only client)',
|
prepare (cmd, options, argv) {
|
if (index.normalizeArg(argv.modern)) {
|
options.modern = 'client';
|
}
|
}
|
},
|
'force-build': {
|
type: 'boolean',
|
default: false,
|
description: 'Force to build the application with webpack'
|
},
|
'fail-on-error': {
|
type: 'boolean',
|
default: false,
|
description: 'Exit with non-zero status code if there are errors when generating pages'
|
}
|
},
|
async run (cmd) {
|
const config = await cmd.getNuxtConfig({ dev: false });
|
|
// Disable analyze if set by the nuxt config
|
config.build = config.build || {};
|
config.build.analyze = false;
|
|
// Full static
|
if (config.target === utils.TARGETS.static) {
|
await ensureBuild(cmd);
|
await generate$1(cmd);
|
return
|
}
|
|
// Forcing static target anyway
|
config.target = utils.TARGETS.static;
|
consola__default['default'].warn(`When using \`nuxt generate\`, you should set \`target: 'static'\` in your \`nuxt.config\`\n 👉 Learn more about it on https://go.nuxtjs.dev/static-target`);
|
|
// Set flag to keep the prerendering behaviour
|
config._legacyGenerate = true;
|
if (config.build) {
|
// https://github.com/nuxt/nuxt.js/issues/7390
|
config.build.parallel = false;
|
}
|
|
const nuxt = await cmd.getNuxt(config);
|
|
if (cmd.argv.lock) {
|
await cmd.setLock(await index.createLock({
|
id: 'build',
|
dir: nuxt.options.buildDir,
|
root: config.rootDir
|
}));
|
|
nuxt.hook('build:done', async () => {
|
await cmd.releaseLock();
|
|
await cmd.setLock(await index.createLock({
|
id: 'generate',
|
dir: nuxt.options.generate.dir,
|
root: config.rootDir
|
}));
|
});
|
}
|
|
const generator = await cmd.getGenerator(nuxt);
|
await nuxt.server.listen(0);
|
|
const { errors } = await generator.generate({
|
init: true,
|
build: cmd.argv.build
|
});
|
|
await nuxt.close();
|
if (cmd.argv['fail-on-error'] && errors.length > 0) {
|
throw new Error('Error generating pages, exiting with non-zero code')
|
}
|
}
|
};
|
|
exports.default = generate;
|