fix: support throw render error when ssr in production
Vue version
3.3.4
Link to minimal reproduction
Steps to reproduce
I want to catch some errors during vue server-side rendering in node.js instead of defining error handlers inside vue such as app.config.errorHandler. When I use the following code to catch an error, in the development environment vue will throw the error, but in the production environment vue swallows the error, which makes it impossible to catch the error with a catch
const { h, defineComponent, createApp } = require('vue')
const { renderToString } = require('@vue/server-renderer')
const MyComponent = defineComponent({
created() {
console.log(document)
},
render() {
return h('div', 'Hello, Vue!')
}
})
const app = createApp(MyComponent)
renderToString(app).then((html) => {
console.log(html)
}).catch((error) => {
console.error('ssr error', error)
// do something with downgrade to csr mode
})
How to test
$ node issue.js // error can be caught
$ NODE_ENV=production node issue.js // error cannot be caught
The reason for the error is that vue handles error objects differently in development and production environments.
// vue/runtime-core.cjs.js
if (appErrorHandler) {
callWithErrorHandling(
appErrorHandler,
null,
10,
[err, exposedInstance, errorInfo]
);
return;
}
}
logError(err, type, contextVNode, throwInDev);
}
function logError(err, type, contextVNode, throwInDev = true) {
{
const info = ErrorTypeStrings[type];
if (contextVNode) {
pushWarningContext(contextVNode);
}
warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
if (contextVNode) {
popWarningContext();
}
if (throwInDev) {
throw err;
} else {
console.error(err);
}
}
}
In production environments vue will not throw error
// vue/runtime-core.cjs.prod.js
const appErrorHandler = instance.appContext.config.errorHandler;
if (appErrorHandler) {
callWithErrorHandling(
appErrorHandler,
null,
10,
[err, exposedInstance, errorInfo]
);
return;
}
}
logError(err, type, contextVNode, throwInDev);
}
function logError(err, type, contextVNode, throwInDev = true) {
{
console.error(err);
}
}
What is expected?
We can use try catch some error during vue rendering process
What is actually happening?
try catch cannot catch some error during vue rendering process
System Info
No response
Any additional comments?
For the reasons mentioned aboveļ¼Perhaps a configuration could be added here to decide whether or not to throw an error in the production environment
I'm not even using SSR, but I just ran into this same issue when trying to add in a global unhandledrejection
listener to show errors in my app. Bizarre behavior to have this functionality change between dev and prod!