vue-cli3 webpack4 服务端渲染 bug Failed to resolve async component

发布于 2022-09-11 15:34:12 字数 4133 浏览 21 评论 0

项目: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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

合久必婚 2022-09-18 15:34:12

多数情况:当router(异步加载)使用code splited才会有这样的问题。

原因:是在用了一些plugins,然后在 vue-ssr-server-bundle 中生成了一些document之类global变量。而这些是定义在browser中的,在server端出现并执行当然就会报错了。

只有改为同步router就能规避这样的错误,不过就不能用懒加载路由了(目前没找到可行的方案)。但如果你在component中用到window、document等全局函数可以引入 jsdom 来人工造一个解决。

<script>
const {
    JSDOM
} = require('jsdom'); // document undefined
export default {
    name: 'List1View',
    computed: {
        items() {
            return this.$store.state['items']
        }
    },
    asyncData({ store }) {
        const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
            'url': 'http://localhost:3000'
        });
        dom.window.document.getElementById('test');//demo
        return store.dispatch('fetchItem', {
            id: 111
        })
    }
}
</script>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文