vue-cli3 webpack4 服务端渲染 bug Failed to resolve async component
项目:vue-cli3 的初始项目,包含 vue-router
错误
在做 ssr 渲染时,router.js 中使用了路由懒加载,然后用webpack打包两个入口的代码时,打包成功了,但是启动服务端端口时访问主页面出错了,生产环境访问出错原因是:
[vue-router] Failed to resolve async component default: ReferenceError: document is not defined
[vue-router] uncaught error during route navigation:
ReferenceError: document is not defined
at n.(anonymous function).n.(anonymous function).i.(anonymous function).u.push.n.(anonymous function).Promise.then.n.(anonymous function) (server-bundle.js:1:497)
at new Promise (<anonymous>)
at Function.module.exports.o.e (server-bundle.js:1:359)
at b (server-bundle.js:1:4079)
at /Users/zhangbo/Desktop/vue-ssr-example/node_modules/vue-router/dist/vue-router.common.js:1776:17
at /Users/zhangbo/Desktop/vue-ssr-example/node_modules/vue-router/dist/vue-router.common.js:1803:66
at Array.map (<anonymous>)
at /Users/zhangbo/Desktop/vue-ssr-example/node_modules/vue-router/dist/vue-router.common.js:1803:38
at Array.map (<anonymous>)
at flatMapComponents (/Users/zhangbo/Desktop/vue-ssr-example/node_modules/vue-router/dist/vue-router.common.js:1802:26)
原因
当组件不是懒加载的时候,是渲染正常的可以访问到,但是懒加载后就会报上面的错误。经过检查,发现在 server-bundle.js 中有调用浏览器 document api 来创建 header 中的 link 标签。问题应该是出现在这里,但是对比了其他 ssr demo 的 webpack 配置也没有找到答案。。希望能有大佬解答一下。。。。
vue.config.js
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const nodeExternals = require('webpack-node-externals')
const merge = require('webpack-merge')
const path = require('path')
const isServer = process.env.WEBPACK_TARGET === 'server'
module.exports = {
configureWebpack: () => {
const Config = {
entry: `./src/entry-${process.env.WEBPACK_TARGET}.js`,
devtool: 'source-map',
target: isServer ? 'node' : 'web'
}
if (process.env.WEBPACK_TARGET === 'server') {
Config.output = { libraryTarget: 'commonjs2', filename: 'server-bundle.js' }
Config.externals = nodeExternals({ whitelist: [/\.css$/] })
Config.plugins = [new VueSSRServerPlugin()]
} else {
Config.plugins = [new VueSSRClientPlugin()]
}
console.log(Config)
return Config
},
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
merge(options, {
optimizeSSR: false
})
})
config.plugin('html')
.tap(args => {
args[0].template = path.resolve(__dirname, './src/index.temp.html')
return args
})
}
}
router.js
import Vue from 'vue'
import Router from 'vue-router'
// import Home from './views/Home.vue'
const Home = () => import('./views/Home.vue')
Vue.use(Router)
export function createRouter () {
return new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
}
]
})
}
打包后访问首页,服务器返回,但页面空白,并且报错 document undefined
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>{{title}}</title><link href=/css/chunk-67b7f2f3.42d2cf04.css rel=prefetch><link href=/js/about.1df3e7f5.js rel=prefetch><link href=/js/chunk-67b7f2f3.7f2bbd0a.js rel=prefetch><link href=/css/main.192eb16d.css rel=preload as=style><link href=/js/chunk-vendors.d536d49e.js rel=preload as=script><link href=/js/main.f21f17e6.js rel=preload as=script><link href=/css/main.192eb16d.css rel=stylesheet></head><body><script src=/js/chunk-vendors.d536d49e.js></script><script src=/js/main.f21f17e6.js></script></body></html>
非常感谢。。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
多数情况:当router(异步加载)使用code splited才会有这样的问题。
原因:是在用了一些plugins,然后在 vue-ssr-server-bundle 中生成了一些document之类global变量。而这些是定义在browser中的,在server端出现并执行当然就会报错了。
只有改为同步router就能规避这样的错误,不过就不能用懒加载路由了(目前没找到可行的方案)。但如果你在component中用到window、document等全局函数可以引入 jsdom 来人工造一个解决。