Skip to content

Commit

Permalink
feat: improve production debugging dx (#7463)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Jun 9, 2020
1 parent 2abbb99 commit 796282c
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 148 deletions.
6 changes: 3 additions & 3 deletions packages/cli/test/unit/__snapshots__/webpack.test.js.snap
Expand Up @@ -567,7 +567,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"loader\\": \\"url-loader\\",
\\"options\\": Object {
\\"limit\\": 1000,
\\"name\\": \\"img/[contenthash:7].[ext]\\",
\\"name\\": \\"img/[name].[contenthash:7].[ext]\\",
},
},
],
Expand All @@ -579,7 +579,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"loader\\": \\"url-loader\\",
\\"options\\": Object {
\\"limit\\": 1000,
\\"name\\": \\"fonts/[contenthash:7].[ext]\\",
\\"name\\": \\"fonts/[name].[contenthash:7].[ext]\\",
},
},
],
Expand All @@ -590,7 +590,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"loader\\": \\"file-loader\\",
\\"options\\": Object {
\\"name\\": \\"videos/[contenthash:7].[ext]\\",
\\"name\\": \\"videos/[name].[contenthash:7].[ext]\\",
},
},
],
Expand Down
12 changes: 6 additions & 6 deletions packages/config/src/config/build.js
Expand Up @@ -14,12 +14,12 @@ export default () => ({
serverURLPolyfill: 'url',
filenames: {
// { isDev, isClient, isServer }
app: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[contenthash].js',
chunk: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[contenthash].js',
css: ({ isDev }) => isDev ? '[name].css' : '[contenthash].css',
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[contenthash:7].[ext]',
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[contenthash:7].[ext]',
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[contenthash:7].[ext]'
app: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[name].[contenthash:7].js',
chunk: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[name].[contenthash:7].js',

This comment has been minimized.

Copy link
@scellige

scellige Jul 8, 2020

@pi0 Hello!
In the build on a production there are two files (js and css) in the directory commons with a name starts from dot. These files return 404 error.
The problem appears only in server mode build (nuxt build).
If I put previous values in fields chunk and css problem doesn't appears.

css: ({ isDev }) => isDev ? '[name].css' : '[name].[contenthash:7].css',
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[name].[contenthash:7].[ext]',
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[name].[contenthash:7].[ext]',
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[name].[contenthash:7].[ext]'
},
loaders: {
file: {},
Expand Down
12 changes: 6 additions & 6 deletions packages/config/test/config/build.test.js
Expand Up @@ -15,12 +15,12 @@ describe('config: build', () => {
test('should return prod filenames', () => {
const { filenames } = buildConfig()
const env = { isDev: false }
expect(filenames.app(env)).toEqual('[contenthash].js')
expect(filenames.chunk(env)).toEqual('[contenthash].js')
expect(filenames.css(env)).toEqual('[contenthash].css')
expect(filenames.img(env)).toEqual('img/[contenthash:7].[ext]')
expect(filenames.font(env)).toEqual('fonts/[contenthash:7].[ext]')
expect(filenames.video(env)).toEqual('videos/[contenthash:7].[ext]')
expect(filenames.app(env)).toEqual('[name].[contenthash:7].js')
expect(filenames.chunk(env)).toEqual('[name].[contenthash:7].js')
expect(filenames.css(env)).toEqual('[name].[contenthash:7].css')
expect(filenames.img(env)).toEqual('img/[name].[contenthash:7].[ext]')
expect(filenames.font(env)).toEqual('fonts/[name].[contenthash:7].[ext]')
expect(filenames.video(env)).toEqual('videos/[name].[contenthash:7].[ext]')
})

test('should return modern filenames', () => {
Expand Down
94 changes: 48 additions & 46 deletions packages/server/src/middleware/error.js
Expand Up @@ -4,20 +4,14 @@ import consola from 'consola'

import Youch from '@nuxtjs/youch'

export default ({ resources, options }) => async function errorMiddleware (err, req, res, next) {
// ensure statusCode, message and name fields

const error = {
statusCode: err.statusCode || 500,
message: err.message || 'Nuxt Server Error',
name: !err.name || err.name === 'Error' ? 'NuxtServerError' : err.name,
headers: err.headers
}
export default ({ resources, options }) => async function errorMiddleware (_error, req, res, next) {
// Normalize error
const error = normalizeError(_error, options)

const sendResponse = (content, type = 'text/html') => {
// Set Headers
res.statusCode = error.statusCode
res.statusMessage = error.name
res.statusMessage = 'RuntimeError'
res.setHeader('Content-Type', type + '; charset=utf-8')
res.setHeader('Content-Length', Buffer.byteLength(content))
res.setHeader('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
Expand All @@ -43,9 +37,10 @@ export default ({ resources, options }) => async function errorMiddleware (err,
// Use basic errors when debug mode is disabled
if (!options.debug) {
// We hide actual errors from end users, so show them on server logs
if (err.statusCode !== 404) {
consola.error(err)
if (error.statusCode !== 404) {
consola.error(error)
}

// Json format is compatible with Youch json responses
const json = {
status: error.statusCode,
Expand All @@ -61,25 +56,11 @@ export default ({ resources, options }) => async function errorMiddleware (err,
return
}

const errorFull = err instanceof Error
? err
: typeof err === 'string'
? new Error(err)
: new Error(err.message || JSON.stringify(err))

errorFull.name = error.name
errorFull.statusCode = error.statusCode
errorFull.stack = err.stack || undefined

// Show stack trace
const youch = new Youch(
errorFull,
error,
req,
readSourceFactory({
srcDir: options.srcDir,
rootDir: options.rootDir,
buildDir: options.buildDir
}),
readSource,
options.router.base,
true
)
Expand All @@ -93,17 +74,21 @@ export default ({ resources, options }) => async function errorMiddleware (err,
sendResponse(html)
}

const readSourceFactory = ({ srcDir, rootDir, buildDir }) => async function readSource (frame) {
// Remove webpack:/// & query string from the end
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : null
frame.fileName = sanitizeName(frame.fileName)
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : null

// Return if fileName is unknown
if (!frame.fileName) {
return
const normalizeError = (_error, { srcDir, rootDir, buildDir }) => {
if (typeof _error === 'string') {
_error = { message: _error }
} else if (!_error) {
_error = { message: '<empty>' }
}

// Possible paths for file
const error = new Error()
error.message = _error.message
error.name = _error.name
error.statusCode = _error.statusCode || 500
error.headers = _error.headers

const searchPath = [
srcDir,
rootDir,
Expand All @@ -112,17 +97,34 @@ const readSourceFactory = ({ srcDir, rootDir, buildDir }) => async function read
process.cwd()
]

// Scan filesystem for real source
for (const pathDir of searchPath) {
const fullPath = path.resolve(pathDir, frame.fileName)
const source = await fs.readFile(fullPath, 'utf-8').catch(() => null)
if (source) {
frame.contents = source
frame.fullPath = fullPath
if (path.isAbsolute(frame.fileName)) {
frame.fileName = path.relative(rootDir, fullPath)
const findInPaths = (fileName) => {
for (const dir of searchPath) {
const fullPath = path.resolve(dir, fileName)
if (fs.existsSync(fullPath)) {
return fullPath
}
return
}
return fileName
}

error.stack = (_error.stack || '')
.split('\n')
.map((line) => {
const match = line.match(/\(([^)]+)\)|([^\s]+\.[^\s]+):/)
if (!match) {
return line
}
const src = match[1] || match[2] || ''
return line.replace(src, findInPaths(sanitizeName(src)))
})
.join('\n')

return error
}

async function readSource (frame) {
if (fs.existsSync(frame.fileName)) {
frame.fullPath = frame.fileName // Youch BW compat
frame.contents = await fs.readFile(frame.fileName, 'utf-8')
}
}

0 comments on commit 796282c

Please sign in to comment.