You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue SSR应用渲染失败求助:生产环境构建报document未定义错误

Vue SSR Production Build Fails with "ReferenceError: document is not defined"

我正在学习创建Vue SSR应用,遵循官方指南。我的npm scripts配置如下:

"clean": "rimraf ./dist", 
"start": "node .", 
"build:client": "NODE_ENV=production webpack --config webpack/client.js --progress --hide-modules", 
"build:server": "NODE_ENV=production webpack --config webpack/server.js --progress --hide-modules", 
"build": "yarn clean; yarn build:client; yarn build:server"

执行npm run build; npm run start后应用运行失败,访问localhost:8000时出现如下错误:

ReferenceError: document is not defined at promises.push.installedCssChunks.(anonymous function).Promise.then.installedCssChunks.(anonymous function) (webpack/bootstrap:52:0) at new Promise (<anonymous>) at Function.requireEnsure [as e] (webpack/bootstrap:49:0) at component (src/router.js:10:36) at /Users/admin.hoa.nguyen/Demos/vue-ssr/node_modules/vue-router/dist/vue-router.common.js:1778:17 at /Users/admin.hoa.nguyen/Demos/vue-ssr/node_modules/vue-router/dist/vue-router.common.js:1805:66 at Array.map (<anonymous>) at /Users/admin.hoa.nguyen/Demos/vue-ssr/node_modules/vue-router/dist/vue-router.common.js:1805:38 at Array.map (<anonymous>) at flatMapComponents (/Users/admin.hoa.nguyen/Demos/vue-ssr/node_modules/vue-router/dist/vue-router.common.js:1804:26)

但将服务端构建的NODE_ENV改为development时,应用可正常运行。


问题原因

这个错误的核心是服务端渲染过程中代码尝试访问了浏览器专属的document对象。生产环境下webpack的代码分割/异步加载逻辑(比如你路由里的异步组件)会触发CSS加载相关的代码,而这些代码默认会尝试用document插入样式——但服务端根本没有浏览器环境的DOM对象,所以报错。开发环境服务端构建时,webpack的优化逻辑没那么激进,或者相关代码被跳过了,所以没触发这个问题。

解决方案

1. 给服务端webpack配置明确标记服务端环境

在你的webpack/server.js里添加DefinePlugin,告诉Vue和相关插件当前是服务端环境,它们会自动禁用浏览器特有的逻辑:

const webpack = require('webpack');

module.exports = {
  // ... 其他配置
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.VUE_ENV': '"server"' // 关键:标记服务端环境
    })
  ]
};

2. 优化Vue组件的服务端渲染配置

修改vue-loader的配置,开启optimizeSSR选项,禁用服务端渲染时的DOM相关操作:

// 同样在webpack/server.js的module.rules里
{
  test: /\.vue$/,
  loader: 'vue-loader',
  options: {
    optimizeSSR: true // 阻止组件在服务端执行DOM操作
  }
}

3. 处理异步组件的CSS加载

如果你的异步组件里有CSS,生产环境下要避免在服务端加载这些样式。可以:

  • 用extract-text-webpack-plugin(Vue 2)把客户端的CSS提取到单独文件,服务端打包时不处理CSS的DOM插入逻辑;
  • 或者在组件里通过process.env.VUE_ENV判断,只在客户端执行样式相关操作:
<script>
export default {
  mounted() {
    // 只在客户端执行需要document的逻辑
    if (process.env.VUE_ENV === 'client') {
      // 比如动态加载样式等操作
    }
  }
}
</script>

4. 检查路由的异步组件定义

错误指向src/router.js第10行的组件加载,确保你的异步组件是标准的Vue SSR兼容写法:

// 正确的异步组件写法(支持服务端渲染)
const Home = () => import('./views/Home.vue')

const router = new VueRouter({
  routes: [
    { path: '/', component: Home }
  ]
})

5. 确保服务端入口是无状态的

服务端入口文件要每次请求都创建新的Vue、Router实例,不要用单例,避免交叉请求污染:

// src/entry-server.js
import Vue from 'vue'
import App from './App.vue'
import createRouter from './router'

export default function createApp(context) {
  const router = createRouter()
  const app = new Vue({
    router,
    context,
    render: h => h(App)
  })
  return { app, router }
}

额外排查点

  • 如果用了第三方依赖,检查是否有库在服务端执行时访问document,可以用webpack-node-externals把node_modules排除在服务端打包之外,避免打包浏览器专属库;
  • 确认build:server脚本的环境变量是否正确传递(Windows系统建议用cross-env来设置NODE_ENV,避免环境变量不生效的问题)。

内容的提问来源于stack exchange,提问作者Harry Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:30:05