mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-06 21:10:38 +00:00
imrpove nuxt-generate error report summary
This commit is contained in:
parent
061059beb4
commit
118d3fb8c2
@ -104,15 +104,8 @@ if (options.mode !== 'spa') {
|
||||
debug(`HTML Files generated in ${duration}s`)
|
||||
|
||||
if (errors.length) {
|
||||
const report = errors.map(({ type, route, error }) => {
|
||||
/* istanbul ignore if */
|
||||
if (type === 'unhandled') {
|
||||
return `Route: '${route}'\n${error.stack}`
|
||||
} else {
|
||||
return `Route: '${route}' thrown an error: \n` + JSON.stringify(error)
|
||||
}
|
||||
})
|
||||
Utils.printError(report.join('\n\n'), 'Generate errors summary:')
|
||||
/* eslint-disable no-console */
|
||||
console.log('\n' + errors.toString())
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -86,17 +86,11 @@ nuxt.hook('generate:done', (generator, errors) => {
|
||||
const duration = Math.round((Date.now() - s) / 100) / 10
|
||||
|
||||
debug(`HTML Files generated in ${duration}s`)
|
||||
|
||||
console.log(errors.length)
|
||||
if (errors.length) {
|
||||
const report = errors.map(({ type, route, error }) => {
|
||||
/* istanbul ignore if */
|
||||
if (type === 'unhandled') {
|
||||
return `Route: '${route}'\n${error.stack}`
|
||||
} else {
|
||||
return `Route: '${route}' thrown an error: \n` + JSON.stringify(error)
|
||||
}
|
||||
})
|
||||
Utils.printError(report.join('\n\n'), 'Generate errors summary:')
|
||||
/* eslint-disable no-console */
|
||||
console.log('\n Generate errors summary:')
|
||||
console.log('\n' + errors.toString())
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,8 +1,23 @@
|
||||
const { copy, remove, writeFile, mkdirp, removeSync, existsSync } = require('fs-extra')
|
||||
const {
|
||||
copy,
|
||||
remove,
|
||||
writeFile,
|
||||
mkdirp,
|
||||
removeSync,
|
||||
existsSync
|
||||
} = require('fs-extra')
|
||||
const _ = require('lodash')
|
||||
const { resolve, join, dirname, sep } = require('path')
|
||||
const { minify } = require('html-minifier')
|
||||
const { isUrl, promisifyRoute, waitFor, flatRoutes } = require('../common/utils')
|
||||
const Chalk = require('chalk')
|
||||
|
||||
const {
|
||||
isUrl,
|
||||
promisifyRoute,
|
||||
waitFor,
|
||||
flatRoutes,
|
||||
pe
|
||||
} = require('../common/utils')
|
||||
|
||||
module.exports = class Generator {
|
||||
constructor(nuxt, builder) {
|
||||
@ -14,7 +29,10 @@ module.exports = class Generator {
|
||||
this.staticRoutes = resolve(this.options.srcDir, 'static')
|
||||
this.srcBuiltPath = resolve(this.options.buildDir, 'dist')
|
||||
this.distPath = resolve(this.options.rootDir, this.options.generate.dir)
|
||||
this.distNuxtPath = join(this.distPath, (isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath))
|
||||
this.distNuxtPath = join(
|
||||
this.distPath,
|
||||
isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath
|
||||
)
|
||||
}
|
||||
|
||||
async generate({ build = true, init = true } = {}) {
|
||||
@ -25,7 +43,7 @@ module.exports = class Generator {
|
||||
const errors = await this.generateRoutes(routes)
|
||||
await this.afterGenerate()
|
||||
|
||||
// done hook
|
||||
// Done hook
|
||||
await this.nuxt.callHook('generate:done', this, errors)
|
||||
|
||||
return { errors }
|
||||
@ -57,14 +75,20 @@ module.exports = class Generator {
|
||||
let generateRoutes = []
|
||||
if (this.options.router.mode !== 'hash') {
|
||||
try {
|
||||
generateRoutes = await promisifyRoute(this.options.generate.routes || [], ...args)
|
||||
generateRoutes = await promisifyRoute(
|
||||
this.options.generate.routes || [],
|
||||
...args
|
||||
)
|
||||
} catch (e) {
|
||||
console.error('Could not resolve routes') // eslint-disable-line no-console
|
||||
throw e // eslint-disable-line no-unreachable
|
||||
}
|
||||
}
|
||||
// Generate only index.html for router.mode = 'hash'
|
||||
let routes = (this.options.router.mode === 'hash') ? ['/'] : flatRoutes(this.options.router.routes)
|
||||
let routes =
|
||||
this.options.router.mode === 'hash'
|
||||
? ['/']
|
||||
: flatRoutes(this.options.router.routes)
|
||||
routes = this.decorateWithPayloads(routes, generateRoutes)
|
||||
|
||||
// extendRoutes hook
|
||||
@ -79,15 +103,43 @@ module.exports = class Generator {
|
||||
// Start generate process
|
||||
while (routes.length) {
|
||||
let n = 0
|
||||
await Promise.all(routes.splice(0, this.options.generate.concurrency).map(async ({ route, payload }) => {
|
||||
await waitFor(n++ * this.options.generate.interval)
|
||||
await this.generateRoute({ route, payload, errors })
|
||||
}))
|
||||
await Promise.all(
|
||||
routes
|
||||
.splice(0, this.options.generate.concurrency)
|
||||
.map(async ({ route, payload }) => {
|
||||
await waitFor(n++ * this.options.generate.interval)
|
||||
await this.generateRoute({ route, payload, errors })
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// Improve string representation for errors
|
||||
errors.toString = () => this._formatErrors(errors)
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
_formatErrors(errors) {
|
||||
return errors
|
||||
.map(({ type, route, error }) => {
|
||||
const isHandled = type === 'handled'
|
||||
const bgColor = isHandled ? 'bgYellow' : 'bgRed'
|
||||
const color = isHandled ? 'yellow' : 'red'
|
||||
|
||||
let line =
|
||||
Chalk.black[bgColor](' ROUTE ') + Chalk[color](` ${route}\n\n`)
|
||||
|
||||
if (isHandled) {
|
||||
line += Chalk.grey(JSON.stringify(error, undefined, 2) + '\n')
|
||||
} else {
|
||||
line += Chalk.grey(pe.render(error))
|
||||
}
|
||||
|
||||
return line
|
||||
})
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
async afterGenerate() {
|
||||
const indexPath = join(this.distPath, 'index.html')
|
||||
if (existsSync(indexPath)) {
|
||||
@ -138,14 +190,14 @@ module.exports = class Generator {
|
||||
decorateWithPayloads(routes, generateRoutes) {
|
||||
let routeMap = {}
|
||||
// Fill routeMap for known routes
|
||||
routes.forEach((route) => {
|
||||
routes.forEach(route => {
|
||||
routeMap[route] = {
|
||||
route,
|
||||
payload: null
|
||||
}
|
||||
})
|
||||
// Fill routeMap with given generate.routes
|
||||
generateRoutes.forEach((route) => {
|
||||
generateRoutes.forEach(route => {
|
||||
// route is either a string or like { route : '/my_route/1', payload: {} }
|
||||
const path = _.isString(route) ? route : route.route
|
||||
routeMap[path] = {
|
||||
@ -161,7 +213,10 @@ module.exports = class Generator {
|
||||
const pageErrors = []
|
||||
|
||||
try {
|
||||
const res = await this.nuxt.renderer.renderRoute(route, { _generate: true, payload })
|
||||
const res = await this.nuxt.renderer.renderRoute(route, {
|
||||
_generate: true,
|
||||
payload
|
||||
})
|
||||
html = res.html
|
||||
if (res.error) {
|
||||
pageErrors.push({ type: 'handled', route, error: res.error })
|
||||
@ -171,7 +226,10 @@ module.exports = class Generator {
|
||||
pageErrors.push({ type: 'unhandled', route, error: err })
|
||||
Array.prototype.push.apply(errors, pageErrors)
|
||||
|
||||
await this.nuxt.callHook('generate:routeFailed', { route, errors: pageErrors })
|
||||
await this.nuxt.callHook('generate:routeFailed', {
|
||||
route,
|
||||
errors: pageErrors
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
@ -180,7 +238,9 @@ module.exports = class Generator {
|
||||
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}`)
|
||||
const minifyErr = new Error(
|
||||
`HTML minification failed. Make sure the route generates valid HTML. Failed HTML:\n ${html}`
|
||||
)
|
||||
pageErrors.push({ type: 'unhandled', route, error: minifyErr })
|
||||
}
|
||||
}
|
||||
@ -205,7 +265,11 @@ module.exports = class Generator {
|
||||
await mkdirp(dirname(page.path))
|
||||
await writeFile(page.path, page.html, 'utf8')
|
||||
|
||||
await this.nuxt.callHook('generate:routeCreated', { route, path: page.path, errors: pageErrors })
|
||||
await this.nuxt.callHook('generate:routeCreated', {
|
||||
route,
|
||||
path: page.path,
|
||||
errors: pageErrors
|
||||
})
|
||||
|
||||
if (pageErrors.length) {
|
||||
Array.prototype.push.apply(errors, pageErrors)
|
||||
|
@ -3,26 +3,28 @@ const _ = require('lodash')
|
||||
const PrettyError = require('pretty-error')
|
||||
const Chalk = require('chalk')
|
||||
|
||||
const pe = new PrettyError()
|
||||
exports.pe = new PrettyError()
|
||||
|
||||
exports.printWarn = function (msg, from) {
|
||||
/* eslint-disable no-console */
|
||||
const fromStr = from ? Chalk.yellow(` ${from}\n\n`) : ' '
|
||||
|
||||
console.error('\n' + Chalk.bgYellow.black(' WARN ') + fromStr + msg + '\n')
|
||||
}
|
||||
|
||||
exports.printError = function (_error, from) {
|
||||
/* eslint-disable no-console */
|
||||
const errStr = pe.render(_error)
|
||||
exports.renderError = function (_error, from) {
|
||||
const errStr = exports.pe.render(_error)
|
||||
const fromStr = from ? Chalk.red(` ${from}`) : ''
|
||||
return '\n' + Chalk.bgRed.black(' ERROR ') + fromStr + '\n' + errStr + '\n'
|
||||
}
|
||||
|
||||
console.error('\n' + Chalk.bgRed.black(' ERROR ') + fromStr + '\n')
|
||||
console.error(errStr + '\n')
|
||||
exports.printError = function () {
|
||||
/* eslint-disable no-console */
|
||||
console.error(exports.renderError(...arguments))
|
||||
}
|
||||
|
||||
exports.fatalError = function () {
|
||||
exports.printError(...arguments)
|
||||
/* eslint-disable no-console */
|
||||
console.error(exports.renderError(...arguments))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,6 @@ test.serial('bin/nuxt-generate', async t => {
|
||||
t.true(stderr.includes('Destination folder cleaned'))
|
||||
t.true(stderr.includes('Static & build files copied'))
|
||||
t.true(stderr.includes(`Generate file: ${sep}users${sep}1${sep}index.html`))
|
||||
t.true(stderr.includes('Generate errors summary:'))
|
||||
t.true(stdout.includes('Generate errors summary:'))
|
||||
t.true(stderr.includes('Generate done'))
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user