mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-21 07:59:33 +00:00
feat: improve production debugging dx (#7463)
This commit is contained in:
parent
2abbb9957d
commit
796282ceec
@ -567,7 +567,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
|
|||||||
\\"loader\\": \\"url-loader\\",
|
\\"loader\\": \\"url-loader\\",
|
||||||
\\"options\\": Object {
|
\\"options\\": Object {
|
||||||
\\"limit\\": 1000,
|
\\"limit\\": 1000,
|
||||||
\\"name\\": \\"img/[contenthash:7].[ext]\\",
|
\\"name\\": \\"img/[name].[contenthash:7].[ext]\\",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -579,7 +579,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
|
|||||||
\\"loader\\": \\"url-loader\\",
|
\\"loader\\": \\"url-loader\\",
|
||||||
\\"options\\": Object {
|
\\"options\\": Object {
|
||||||
\\"limit\\": 1000,
|
\\"limit\\": 1000,
|
||||||
\\"name\\": \\"fonts/[contenthash:7].[ext]\\",
|
\\"name\\": \\"fonts/[name].[contenthash:7].[ext]\\",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -590,7 +590,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
|
|||||||
Object {
|
Object {
|
||||||
\\"loader\\": \\"file-loader\\",
|
\\"loader\\": \\"file-loader\\",
|
||||||
\\"options\\": Object {
|
\\"options\\": Object {
|
||||||
\\"name\\": \\"videos/[contenthash:7].[ext]\\",
|
\\"name\\": \\"videos/[name].[contenthash:7].[ext]\\",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -14,12 +14,12 @@ export default () => ({
|
|||||||
serverURLPolyfill: 'url',
|
serverURLPolyfill: 'url',
|
||||||
filenames: {
|
filenames: {
|
||||||
// { isDev, isClient, isServer }
|
// { isDev, isClient, isServer }
|
||||||
app: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[contenthash].js',
|
app: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[name].[contenthash:7].js',
|
||||||
chunk: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[contenthash].js',
|
chunk: ({ isDev, isModern }) => isDev ? `${isModern ? 'modern-' : ''}[name].js` : '[name].[contenthash:7].js',
|
||||||
css: ({ isDev }) => isDev ? '[name].css' : '[contenthash].css',
|
css: ({ isDev }) => isDev ? '[name].css' : '[name].[contenthash:7].css',
|
||||||
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[contenthash:7].[ext]',
|
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[name].[contenthash:7].[ext]',
|
||||||
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[contenthash:7].[ext]',
|
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[name].[contenthash:7].[ext]',
|
||||||
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[contenthash:7].[ext]'
|
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[name].[contenthash:7].[ext]'
|
||||||
},
|
},
|
||||||
loaders: {
|
loaders: {
|
||||||
file: {},
|
file: {},
|
||||||
|
@ -15,12 +15,12 @@ describe('config: build', () => {
|
|||||||
test('should return prod filenames', () => {
|
test('should return prod filenames', () => {
|
||||||
const { filenames } = buildConfig()
|
const { filenames } = buildConfig()
|
||||||
const env = { isDev: false }
|
const env = { isDev: false }
|
||||||
expect(filenames.app(env)).toEqual('[contenthash].js')
|
expect(filenames.app(env)).toEqual('[name].[contenthash:7].js')
|
||||||
expect(filenames.chunk(env)).toEqual('[contenthash].js')
|
expect(filenames.chunk(env)).toEqual('[name].[contenthash:7].js')
|
||||||
expect(filenames.css(env)).toEqual('[contenthash].css')
|
expect(filenames.css(env)).toEqual('[name].[contenthash:7].css')
|
||||||
expect(filenames.img(env)).toEqual('img/[contenthash:7].[ext]')
|
expect(filenames.img(env)).toEqual('img/[name].[contenthash:7].[ext]')
|
||||||
expect(filenames.font(env)).toEqual('fonts/[contenthash:7].[ext]')
|
expect(filenames.font(env)).toEqual('fonts/[name].[contenthash:7].[ext]')
|
||||||
expect(filenames.video(env)).toEqual('videos/[contenthash:7].[ext]')
|
expect(filenames.video(env)).toEqual('videos/[name].[contenthash:7].[ext]')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should return modern filenames', () => {
|
test('should return modern filenames', () => {
|
||||||
|
@ -4,20 +4,14 @@ import consola from 'consola'
|
|||||||
|
|
||||||
import Youch from '@nuxtjs/youch'
|
import Youch from '@nuxtjs/youch'
|
||||||
|
|
||||||
export default ({ resources, options }) => async function errorMiddleware (err, req, res, next) {
|
export default ({ resources, options }) => async function errorMiddleware (_error, req, res, next) {
|
||||||
// ensure statusCode, message and name fields
|
// Normalize error
|
||||||
|
const error = normalizeError(_error, options)
|
||||||
const error = {
|
|
||||||
statusCode: err.statusCode || 500,
|
|
||||||
message: err.message || 'Nuxt Server Error',
|
|
||||||
name: !err.name || err.name === 'Error' ? 'NuxtServerError' : err.name,
|
|
||||||
headers: err.headers
|
|
||||||
}
|
|
||||||
|
|
||||||
const sendResponse = (content, type = 'text/html') => {
|
const sendResponse = (content, type = 'text/html') => {
|
||||||
// Set Headers
|
// Set Headers
|
||||||
res.statusCode = error.statusCode
|
res.statusCode = error.statusCode
|
||||||
res.statusMessage = error.name
|
res.statusMessage = 'RuntimeError'
|
||||||
res.setHeader('Content-Type', type + '; charset=utf-8')
|
res.setHeader('Content-Type', type + '; charset=utf-8')
|
||||||
res.setHeader('Content-Length', Buffer.byteLength(content))
|
res.setHeader('Content-Length', Buffer.byteLength(content))
|
||||||
res.setHeader('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
|
res.setHeader('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
|
||||||
@ -43,9 +37,10 @@ export default ({ resources, options }) => async function errorMiddleware (err,
|
|||||||
// Use basic errors when debug mode is disabled
|
// Use basic errors when debug mode is disabled
|
||||||
if (!options.debug) {
|
if (!options.debug) {
|
||||||
// We hide actual errors from end users, so show them on server logs
|
// We hide actual errors from end users, so show them on server logs
|
||||||
if (err.statusCode !== 404) {
|
if (error.statusCode !== 404) {
|
||||||
consola.error(err)
|
consola.error(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Json format is compatible with Youch json responses
|
// Json format is compatible with Youch json responses
|
||||||
const json = {
|
const json = {
|
||||||
status: error.statusCode,
|
status: error.statusCode,
|
||||||
@ -61,25 +56,11 @@ export default ({ resources, options }) => async function errorMiddleware (err,
|
|||||||
return
|
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
|
// Show stack trace
|
||||||
const youch = new Youch(
|
const youch = new Youch(
|
||||||
errorFull,
|
error,
|
||||||
req,
|
req,
|
||||||
readSourceFactory({
|
readSource,
|
||||||
srcDir: options.srcDir,
|
|
||||||
rootDir: options.rootDir,
|
|
||||||
buildDir: options.buildDir
|
|
||||||
}),
|
|
||||||
options.router.base,
|
options.router.base,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -93,17 +74,21 @@ export default ({ resources, options }) => async function errorMiddleware (err,
|
|||||||
sendResponse(html)
|
sendResponse(html)
|
||||||
}
|
}
|
||||||
|
|
||||||
const readSourceFactory = ({ srcDir, rootDir, buildDir }) => async function readSource (frame) {
|
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : null
|
||||||
// Remove webpack:/// & query string from the end
|
|
||||||
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : null
|
|
||||||
frame.fileName = sanitizeName(frame.fileName)
|
|
||||||
|
|
||||||
// Return if fileName is unknown
|
const normalizeError = (_error, { srcDir, rootDir, buildDir }) => {
|
||||||
if (!frame.fileName) {
|
if (typeof _error === 'string') {
|
||||||
return
|
_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 = [
|
const searchPath = [
|
||||||
srcDir,
|
srcDir,
|
||||||
rootDir,
|
rootDir,
|
||||||
@ -112,17 +97,34 @@ const readSourceFactory = ({ srcDir, rootDir, buildDir }) => async function read
|
|||||||
process.cwd()
|
process.cwd()
|
||||||
]
|
]
|
||||||
|
|
||||||
// Scan filesystem for real source
|
const findInPaths = (fileName) => {
|
||||||
for (const pathDir of searchPath) {
|
for (const dir of searchPath) {
|
||||||
const fullPath = path.resolve(pathDir, frame.fileName)
|
const fullPath = path.resolve(dir, fileName)
|
||||||
const source = await fs.readFile(fullPath, 'utf-8').catch(() => null)
|
if (fs.existsSync(fullPath)) {
|
||||||
if (source) {
|
return fullPath
|
||||||
frame.contents = source
|
|
||||||
frame.fullPath = fullPath
|
|
||||||
if (path.isAbsolute(frame.fileName)) {
|
|
||||||
frame.fileName = path.relative(rootDir, 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')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,13 @@ const createServerContext = () => ({
|
|||||||
next: jest.fn()
|
next: jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const errorFileName = 'test-error.js'
|
||||||
|
const createError = () => {
|
||||||
|
const err = new Error('Error!')
|
||||||
|
err.stack = `Error!\n at foo (webpack:///${errorFileName}?foo:1)`
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
describe('server: errorMiddleware', () => {
|
describe('server: errorMiddleware', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
|
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
|
||||||
@ -48,26 +55,21 @@ describe('server: errorMiddleware', () => {
|
|||||||
test('should send html error response', async () => {
|
test('should send html error response', async () => {
|
||||||
const params = createParams()
|
const params = createParams()
|
||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
const error = new Error()
|
const error = {}
|
||||||
error.headers = { 'Custom-Header': 'test' }
|
error.headers = { 'Custom-Header': 'test' }
|
||||||
const ctx = createServerContext()
|
const ctx = createServerContext()
|
||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
expect(consola.error).toBeCalledWith(error)
|
|
||||||
expect(ctx.res.statusCode).toEqual(500)
|
expect(ctx.res.statusCode).toEqual(500)
|
||||||
expect(ctx.res.statusMessage).toEqual('NuxtServerError')
|
expect(ctx.res.statusMessage).toEqual('RuntimeError')
|
||||||
expect(ctx.res.setHeader).toBeCalledTimes(4)
|
expect(ctx.res.setHeader).toBeCalledTimes(4)
|
||||||
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/html; charset=utf-8')
|
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/html; charset=utf-8')
|
||||||
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength('error template'))
|
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength('error template'))
|
||||||
expect(ctx.res.setHeader).nthCalledWith(3, 'Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
|
expect(ctx.res.setHeader).nthCalledWith(3, 'Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
|
||||||
expect(ctx.res.setHeader).nthCalledWith(4, 'Custom-Header', 'test')
|
expect(ctx.res.setHeader).nthCalledWith(4, 'Custom-Header', 'test')
|
||||||
expect(params.resources.errorTemplate).toBeCalledTimes(1)
|
expect(params.resources.errorTemplate).toBeCalledTimes(1)
|
||||||
expect(params.resources.errorTemplate).toBeCalledWith({
|
expect(params.resources.errorTemplate).toBeCalledWith({ status: 500 })
|
||||||
status: 500,
|
|
||||||
message: 'Nuxt Server Error',
|
|
||||||
name: 'NuxtServerError'
|
|
||||||
})
|
|
||||||
expect(ctx.res.end).toBeCalledTimes(1)
|
expect(ctx.res.end).toBeCalledTimes(1)
|
||||||
expect(ctx.res.end).toBeCalledWith('error template', 'utf-8')
|
expect(ctx.res.end).toBeCalledWith('error template', 'utf-8')
|
||||||
})
|
})
|
||||||
@ -77,7 +79,6 @@ describe('server: errorMiddleware', () => {
|
|||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
const error = {
|
const error = {
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
name: 'NuxtTestError',
|
|
||||||
message: 'test error'
|
message: 'test error'
|
||||||
}
|
}
|
||||||
const ctx = createServerContext()
|
const ctx = createServerContext()
|
||||||
@ -92,7 +93,6 @@ describe('server: errorMiddleware', () => {
|
|||||||
}, undefined, 2)
|
}, undefined, 2)
|
||||||
expect(consola.error).not.toBeCalled()
|
expect(consola.error).not.toBeCalled()
|
||||||
expect(ctx.res.statusCode).toEqual(404)
|
expect(ctx.res.statusCode).toEqual(404)
|
||||||
expect(ctx.res.statusMessage).toEqual(error.name)
|
|
||||||
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
||||||
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/json; charset=utf-8')
|
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/json; charset=utf-8')
|
||||||
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errJson))
|
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errJson))
|
||||||
@ -108,22 +108,13 @@ describe('server: errorMiddleware', () => {
|
|||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
const error = new Error('test error')
|
const error = new Error('test error')
|
||||||
error.statusCode = 503
|
error.statusCode = 503
|
||||||
error.name = 'NuxtTestError'
|
|
||||||
const ctx = createServerContext()
|
const ctx = createServerContext()
|
||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
const errHtml = 'youch html'
|
const errHtml = 'youch html'
|
||||||
expect(Youch).toBeCalledTimes(1)
|
|
||||||
expect(Youch).toBeCalledWith(
|
|
||||||
error,
|
|
||||||
ctx.req,
|
|
||||||
expect.any(Function),
|
|
||||||
params.options.router.base,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
expect(ctx.res.statusCode).toEqual(503)
|
expect(ctx.res.statusCode).toEqual(503)
|
||||||
expect(ctx.res.statusMessage).toEqual(error.name)
|
|
||||||
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
||||||
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/html; charset=utf-8')
|
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/html; charset=utf-8')
|
||||||
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errHtml))
|
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errHtml))
|
||||||
@ -139,7 +130,6 @@ describe('server: errorMiddleware', () => {
|
|||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
const error = {
|
const error = {
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
name: 'NuxtTestError',
|
|
||||||
message: 'test error'
|
message: 'test error'
|
||||||
}
|
}
|
||||||
const ctx = createServerContext()
|
const ctx = createServerContext()
|
||||||
@ -148,20 +138,8 @@ describe('server: errorMiddleware', () => {
|
|||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
const errJson = JSON.stringify('youch json', undefined, 2)
|
const errJson = JSON.stringify('youch json', undefined, 2)
|
||||||
const errorFull = new Error(error.message)
|
|
||||||
errorFull.name = error.name
|
|
||||||
errorFull.statusCode = error.statusCode
|
|
||||||
errorFull.stack = undefined
|
|
||||||
expect(Youch).toBeCalledTimes(1)
|
|
||||||
expect(Youch).toBeCalledWith(
|
|
||||||
errorFull,
|
|
||||||
ctx.req,
|
|
||||||
expect.any(Function),
|
|
||||||
params.options.router.base,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
expect(ctx.res.statusCode).toEqual(404)
|
expect(ctx.res.statusCode).toEqual(404)
|
||||||
expect(ctx.res.statusMessage).toEqual(error.name)
|
|
||||||
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
expect(ctx.res.setHeader).toBeCalledTimes(3)
|
||||||
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/json; charset=utf-8')
|
expect(ctx.res.setHeader).nthCalledWith(1, 'Content-Type', 'text/json; charset=utf-8')
|
||||||
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errJson))
|
expect(ctx.res.setHeader).nthCalledWith(2, 'Content-Length', Buffer.byteLength(errJson))
|
||||||
@ -175,24 +153,16 @@ describe('server: errorMiddleware', () => {
|
|||||||
const params = createParams()
|
const params = createParams()
|
||||||
params.options.debug = true
|
params.options.debug = true
|
||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
const error = {}
|
const error = createError()
|
||||||
const ctx = createServerContext()
|
const ctx = createServerContext()
|
||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
const frame = { fileName: 'webpack:///test-error.js?desc=test' }
|
expect(fs.existsSync).nthCalledWith(1, `resolve(${params.options.srcDir}, ${errorFileName})`)
|
||||||
const readSource = Youch.mock.calls[0][2]
|
expect(fs.existsSync).nthCalledWith(2, `resolve(${params.options.rootDir}, ${errorFileName})`)
|
||||||
await readSource(frame)
|
expect(fs.existsSync).nthCalledWith(3, `resolve(join(${params.options.buildDir}, dist, server), ${errorFileName})`)
|
||||||
|
expect(fs.existsSync).nthCalledWith(4, `resolve(${params.options.buildDir}, ${errorFileName})`)
|
||||||
const fileName = 'test-error.js'
|
expect(fs.existsSync).nthCalledWith(5, `resolve(${process.cwd()}, ${errorFileName})`)
|
||||||
expect(frame).toEqual({ fileName })
|
|
||||||
expect(path.resolve).toBeCalledTimes(5)
|
|
||||||
expect(fs.readFile).toBeCalledTimes(5)
|
|
||||||
expect(fs.readFile).nthCalledWith(1, `resolve(${params.options.srcDir}, ${fileName})`, 'utf-8')
|
|
||||||
expect(fs.readFile).nthCalledWith(2, `resolve(${params.options.rootDir}, ${fileName})`, 'utf-8')
|
|
||||||
expect(fs.readFile).nthCalledWith(3, `resolve(join(${params.options.buildDir}, dist, server), ${fileName})`, 'utf-8')
|
|
||||||
expect(fs.readFile).nthCalledWith(4, `resolve(${params.options.buildDir}, ${fileName})`, 'utf-8')
|
|
||||||
expect(fs.readFile).nthCalledWith(5, `resolve(${process.cwd()}, ${fileName})`, 'utf-8')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should return source content after read source', async () => {
|
test('should return source content after read source', async () => {
|
||||||
@ -204,20 +174,20 @@ describe('server: errorMiddleware', () => {
|
|||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
const frame = { fileName: 'webpack:///test-error.js?desc=test' }
|
const frame = { fileName: errorFileName }
|
||||||
const readSource = Youch.mock.calls[0][2]
|
const readSource = Youch.mock.calls[0][2]
|
||||||
|
fs.existsSync.mockImplementationOnce(() => true)
|
||||||
fs.readFile.mockImplementationOnce(() => Promise.resolve('source content'))
|
fs.readFile.mockImplementationOnce(() => Promise.resolve('source content'))
|
||||||
await readSource(frame)
|
await readSource(frame)
|
||||||
|
|
||||||
const fileName = 'test-error.js'
|
|
||||||
expect(frame).toEqual({
|
expect(frame).toEqual({
|
||||||
fileName,
|
fileName: errorFileName,
|
||||||
contents: 'source content',
|
contents: 'source content',
|
||||||
fullPath: `resolve(${params.options.srcDir}, ${fileName})`
|
fullPath: errorFileName
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should return relative fileName if fileName is absolute path', async () => {
|
test('should ignore if source file not exists', async () => {
|
||||||
const params = createParams()
|
const params = createParams()
|
||||||
params.options.debug = true
|
params.options.debug = true
|
||||||
const errorMiddleware = createErrorMiddleware(params)
|
const errorMiddleware = createErrorMiddleware(params)
|
||||||
@ -226,39 +196,11 @@ describe('server: errorMiddleware', () => {
|
|||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
||||||
|
|
||||||
const frame = { fileName: 'webpack:///test-error.js?desc=test' }
|
const frame = { fileName: errorFileName }
|
||||||
const readSource = Youch.mock.calls[0][2]
|
const readSource = Youch.mock.calls[0][2]
|
||||||
fs.readFile.mockImplementationOnce(() => Promise.resolve('source content'))
|
fs.exists.mockReturnValueOnce(false)
|
||||||
path.isAbsolute.mockReturnValueOnce(true)
|
|
||||||
path.relative.mockImplementationOnce((...args) => `relative(${args.join(', ')})`)
|
|
||||||
await readSource(frame)
|
await readSource(frame)
|
||||||
|
expect(frame).toEqual({ fileName: errorFileName })
|
||||||
const fullPath = `resolve(${params.options.srcDir}, test-error.js)`
|
|
||||||
expect(frame).toEqual({
|
|
||||||
fileName: `relative(${params.options.rootDir}, ${fullPath})`,
|
|
||||||
contents: 'source content',
|
|
||||||
fullPath
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should ignore error when reading source', async () => {
|
|
||||||
const params = createParams()
|
|
||||||
params.options.debug = true
|
|
||||||
const errorMiddleware = createErrorMiddleware(params)
|
|
||||||
const error = {}
|
|
||||||
const ctx = createServerContext()
|
|
||||||
|
|
||||||
await errorMiddleware(error, ctx.req, ctx.res, ctx.next)
|
|
||||||
|
|
||||||
const frame = { fileName: 'webpack:///test-error.js?desc=test' }
|
|
||||||
const readSource = Youch.mock.calls[0][2]
|
|
||||||
fs.readFile.mockReturnValueOnce(Promise.reject(new Error('read failed')))
|
|
||||||
await readSource(frame)
|
|
||||||
|
|
||||||
const fileName = 'test-error.js'
|
|
||||||
expect(frame).toEqual({ fileName })
|
|
||||||
expect(path.resolve).toBeCalledTimes(5)
|
|
||||||
expect(fs.readFile).toBeCalledTimes(5)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should return if fileName is unknown when read source', async () => {
|
test('should return if fileName is unknown when read source', async () => {
|
||||||
@ -274,6 +216,6 @@ describe('server: errorMiddleware', () => {
|
|||||||
const readSource = Youch.mock.calls[0][2]
|
const readSource = Youch.mock.calls[0][2]
|
||||||
await readSource(frame)
|
await readSource(frame)
|
||||||
|
|
||||||
expect(frame.fileName).toBeNull()
|
expect(frame.fileName).toBeUndefined()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -56,9 +56,11 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optimization () {
|
optimization () {
|
||||||
|
const { _minifyServer } = this.buildContext.buildOptions
|
||||||
|
|
||||||
return {
|
return {
|
||||||
splitChunks: false,
|
splitChunks: false,
|
||||||
minimizer: this.minimizer()
|
minimizer: _minifyServer ? this.minimizer() : []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,6 +115,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
|
|||||||
}),
|
}),
|
||||||
output: Object.assign({}, config.output, {
|
output: Object.assign({}, config.output, {
|
||||||
filename: 'server.js',
|
filename: 'server.js',
|
||||||
|
chunkFilename: '[name].js',
|
||||||
libraryTarget: 'commonjs2'
|
libraryTarget: 'commonjs2'
|
||||||
}),
|
}),
|
||||||
performance: {
|
performance: {
|
||||||
|
@ -48,7 +48,7 @@ describe('with-config', () => {
|
|||||||
test('/ (preload fonts)', async () => {
|
test('/ (preload fonts)', async () => {
|
||||||
const { html } = await nuxt.server.renderRoute('/')
|
const { html } = await nuxt.server.renderRoute('/')
|
||||||
expect(html).toContain(
|
expect(html).toContain(
|
||||||
'<link rel="preload" href="/test/orion/fonts/7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'
|
'<link rel="preload" href="/test/orion/fonts/roboto.7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user