misc: improve CLI errors

This commit is contained in:
Pooya Parsa 2018-01-11 19:41:50 +03:30
parent 58279166e2
commit 13166bcf78
7 changed files with 121 additions and 84 deletions

View File

@ -6,7 +6,7 @@ process.env.DEBUG = process.env.DEBUG || 'nuxt:*'
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt, Builder, Generator } = require('../')
const { Nuxt, Builder, Generator, Utils } = require('../')
const resolve = require('path').resolve
const debug = require('debug')('nuxt:build')
debug.color = 2 // Force green color
@ -49,8 +49,7 @@ var options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
Utils.fatalError(`Could not load config file`, argv['config-file'])
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
@ -59,7 +58,8 @@ if (typeof options.rootDir !== 'string') {
options.dev = false
// Nuxt Mode
options.mode = (argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
options.mode =
(argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
// Analyze option
options.build = options.build || {}
@ -71,11 +71,15 @@ debug('Building...')
const nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
// Setup hooks
nuxt.hook('error', (_err, from) => Utils.fatalError(_err, from))
if (options.mode !== 'spa') {
// Build for SSR app
builder.build()
builder
.build()
.then(() => debug('Building done'))
.catch((err) => {
.catch(err => {
console.error(err)
process.exit(1)
})
@ -108,7 +112,7 @@ if (options.mode !== 'spa') {
return `Route: '${route}' thrown an error: \n` + JSON.stringify(error)
}
})
console.error('==== Error report ==== \n' + report.join('\n\n')) // eslint-disable-line no-console
Utils.printError(report.join('\n\n'), 'Generate errors')
}
})
@ -116,8 +120,6 @@ if (options.mode !== 'spa') {
nuxt.options.generate.minify = false
// Generate on spa mode
new Generator(nuxt, builder).generate({ build: true }).then(() => {
if (!nuxt.options.dev) {
console.log(`✓ You can now directly upload ${nuxt.options.generate.dir}/ or start server using "nuxt start"`)
}
process.exit(0)
})
}

View File

@ -9,7 +9,7 @@ const debug = require('debug')('nuxt:build')
debug.color = 2 // force green color
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt, Builder } = require('../')
const { Nuxt, Builder, Utils } = require('../')
const chokidar = require('chokidar')
const path = require('path')
const resolve = path.resolve
@ -38,8 +38,7 @@ if (argv.version) {
}
if (argv.hostname === '') {
console.error(`> Provided hostname argument has no value`)
process.exit(1)
Utils.fatalError('Provided hostname argument has no value')
}
if (argv.help) {
@ -72,29 +71,31 @@ let dev = startDev()
let needToRestart = false
// Start watching for nuxt.config.js changes
chokidar
.watch(nuxtConfigFile, nuxtConfig.watchers.chokidar)
.on('all', () => {
debug('[nuxt.config.js] changed')
needToRestart = true
chokidar.watch(nuxtConfigFile, nuxtConfig.watchers.chokidar).on('all', () => {
debug('[nuxt.config.js] changed')
needToRestart = true
dev = dev.then((instance) => {
if (needToRestart === false) return instance
needToRestart = false
dev = dev.then(instance => {
if (needToRestart === false) return instance
needToRestart = false
debug('Rebuilding the app...')
return startDev(instance)
})
debug('Rebuilding the app...')
return startDev(instance)
})
})
function startDev(oldInstance) {
// Get latest environment variables
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
const port =
argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host =
argv.hostname ||
process.env.HOST ||
process.env.npm_package_config_nuxt_host
// Error handler
const onError = (err, instance) => {
debug('Error while reloading [nuxt.config.js]', err)
Utils.printError(err)
return Promise.resolve(instance) // Wait for next reload
}
@ -118,18 +119,30 @@ function startDev(oldInstance) {
return onError(err, instance || oldInstance)
}
return Promise.resolve()
.then(() => oldInstance && oldInstance.builder ? oldInstance.builder.unwatch() : Promise.resolve())
// Start build
.then(() => builder.build())
// Close old nuxt after successful build
.then(() => oldInstance && oldInstance.nuxt ? oldInstance.nuxt.close() : Promise.resolve())
// Start listening
.then(() => nuxt.listen(port, host))
// Pass new nuxt to watch chain
.then(() => instance)
// Handle errors
.catch((err) => onError(err, instance))
return (
Promise.resolve()
.then(
() =>
oldInstance && oldInstance.builder
? oldInstance.builder.unwatch()
: Promise.resolve()
)
// Start build
.then(() => builder.build())
// Close old nuxt after successful build
.then(
() =>
oldInstance && oldInstance.nuxt
? oldInstance.nuxt.close()
: Promise.resolve()
)
// Start listening
.then(() => nuxt.listen(port, host))
// Pass new nuxt to watch chain
.then(() => instance)
// Handle errors
.catch(err => onError(err, instance))
)
}
function loadNuxtConfig() {
@ -139,8 +152,7 @@ function loadNuxtConfig() {
delete require.cache[nuxtConfigFile]
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
Utils.fatalError('Could not load config file: ' + argv['config-file'])
}
if (typeof options.rootDir !== 'string') {
@ -151,7 +163,8 @@ function loadNuxtConfig() {
options.dev = true
// Nuxt Mode
options.mode = (argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
options.mode =
(argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
return options
}

View File

@ -8,7 +8,7 @@ const fs = require('fs')
const parseArgs = require('minimist')
const debug = require('debug')('nuxt:generate')
const { Nuxt, Builder, Generator } = require('../')
const { Nuxt, Builder, Generator, Utils } = require('../')
const resolve = require('path').resolve
const argv = parseArgs(process.argv.slice(2), {
@ -49,8 +49,7 @@ var options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
Utils.fatalError('Could not load config file: ' + argv['config-file'])
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
@ -58,7 +57,8 @@ if (typeof options.rootDir !== 'string') {
options.dev = false // Force production mode (no webpack middleware called)
// Nuxt Mode
options.mode = (argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
options.mode =
(argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
debug('Generating...')
const nuxt = new Nuxt(options)
@ -72,19 +72,17 @@ const generateOptions = {
const s = Date.now()
nuxt.hook('generate:distRemoved', function () {
debug('Destination folder cleaned')
})
// Setup hooks
nuxt.hook('generate:distCopied', function () {
debug('Static & build files copied')
})
nuxt.hook('error', (_err, from) => Utils.fatalError(_err, from))
nuxt.hook('generate:page', function (page) {
debug('Generate file: ' + page.path)
})
nuxt.hook('generate:distRemoved', () => debug('Destination folder cleaned'))
nuxt.hook('generate:done', function (generator, errors) {
nuxt.hook('generate:distCopied', () => debug('Static & build files copied'))
nuxt.hook('generate:page', page => debug('Generate file: ' + page.path))
nuxt.hook('generate:done', (generator, errors) => {
const duration = Math.round((Date.now() - s) / 100) / 10
debug(`HTML Files generated in ${duration}s`)
@ -98,16 +96,16 @@ nuxt.hook('generate:done', function (generator, errors) {
return `Route: '${route}' thrown an error: \n` + JSON.stringify(error)
}
})
console.error('==== Error report ==== \n' + report.join('\n\n')) // eslint-disable-line no-console
Utils.printError(report.join('\n\n'), 'generate')
}
})
generator.generate(generateOptions)
generator
.generate(generateOptions)
.then(() => {
debug('Generate done')
process.exit(0)
})
.catch((err) => {
console.error(err)
process.exit(1)
.catch(err => {
Utils.fatalError(err)
})

View File

@ -3,7 +3,7 @@
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt } = require('../')
const { Nuxt, Utils } = require('../')
const { resolve } = require('path')
const argv = parseArgs(process.argv.slice(2), {
@ -23,8 +23,7 @@ const argv = parseArgs(process.argv.slice(2), {
})
if (argv.hostname === '') {
console.error(`> Provided hostname argument has no value`)
process.exit(1)
Utils.fatalError('Provided hostname argument has no value')
}
if (argv.help) {
@ -53,8 +52,7 @@ let options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
Utils.fatalError('Could not load config file: ' + argv['config-file'])
}
if (typeof options.rootDir !== 'string') {
@ -65,27 +63,39 @@ if (typeof options.rootDir !== 'string') {
options.dev = false
// Nuxt Mode
options.mode = (argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
options.mode =
(argv['spa'] && 'spa') || (argv['universal'] && 'universal') || options.mode
const nuxt = new Nuxt(options)
// Setup hooks
nuxt.hook('error', (_err, from) => Utils.fatalError(_err, from))
// Check if project is built for production
const distDir = resolve(nuxt.options.rootDir, nuxt.options.buildDir || '.nuxt', 'dist')
const distDir = resolve(
nuxt.options.rootDir,
nuxt.options.buildDir || '.nuxt',
'dist'
)
if (!fs.existsSync(distDir)) {
console.error('> No build files found, please run `nuxt build` before launching `nuxt start`')
process.exit(1)
Utils.fatalError(
'No build files found, please run `nuxt build` before launching `nuxt start`'
)
}
// Check if SSR Bundle is required
if (nuxt.options.render.ssr === true) {
const ssrBundlePath = resolve(distDir, 'server-bundle.json')
if (!fs.existsSync(ssrBundlePath)) {
console.error('> No SSR build! Please start with `nuxt start --spa` or build using `nuxt build --universal`')
process.exit(1)
Utils.fatalError(
'No SSR build! Please start with `nuxt start --spa` or build using `nuxt build --universal`'
)
}
}
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
const port =
argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host =
argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
nuxt.listen(port, host)

View File

@ -15,12 +15,17 @@ exports.printWarn = function (msg, from) {
exports.printError = function (_error, from) {
/* eslint-disable no-console */
const errStr = pe.render(_error)
const fromStr = from ? Chalk.red(` ${from}\n`) : ' '
const fromStr = from ? Chalk.red(` ${from}`) : ''
console.error('\n' + Chalk.bgRed.black(' ERROR ') + fromStr)
console.error('\n' + Chalk.bgRed.black(' ERROR ') + fromStr + '\n')
console.error(errStr + '\n')
}
exports.fatalError = function () {
exports.printError(...arguments)
process.exit(1)
}
exports.encodeHtml = function encodeHtml(str) {
return str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
}

View File

@ -2,7 +2,7 @@ const path = require('path')
const fs = require('fs')
const { uniq } = require('lodash')
const hash = require('hash-sum')
const { chainFn, sequence, printError, printWarn } = require('../common/utils')
const { chainFn, sequence, printWarn } = require('../common/utils')
module.exports = class ModuleContainer {
constructor(nuxt) {
@ -116,8 +116,7 @@ module.exports = class ModuleContainer {
try {
handler = require(this.nuxt.resolvePath(src))
} catch (err) {
printError(err)
throw new Error('Error while resolving module: ' + src)
this.nuxt.onError(err, src)
}
}

View File

@ -18,6 +18,7 @@ module.exports = class Nuxt {
this.options = Options.from(options)
this.initialized = false
this.onError = this.onError.bind(this)
// Hooks
this._hooks = {}
@ -28,16 +29,14 @@ module.exports = class Nuxt {
this.renderer = new Renderer(this)
// Backward compatibility
this.errorHandler = this.onError
this.render = this.renderer.app
this.renderRoute = this.renderer.renderRoute.bind(this.renderer)
this.renderAndGetWindow = this.renderer.renderAndGetWindow.bind(
this.renderer
)
this._ready = this.ready().catch(err => {
this.callHook('error', err)
printError(err)
})
this._ready = this.ready().catch(err => this.onError(err))
}
static get version() {
@ -102,6 +101,17 @@ module.exports = class Nuxt {
this._hooks[name].push(fn)
}
onError(err, from = 'Nuxt error') {
// Log error to the console if there is not any error listener
if (!this._hooks['error']) {
printError(err, from)
return
}
// Call error hooks
this.callHook('error', err, from)
}
async callHook(name, ...args) {
if (!this._hooks[name]) {
return
@ -110,7 +120,7 @@ module.exports = class Nuxt {
try {
await sequence(this._hooks[name], fn => fn(...args))
} catch (err) {
printError(err, name)
this.onError(err, name)
}
}