Nuxt.js开启SSR模式后出现window is not defined错误的全局解决方案咨询
全局解决Nuxt.js SSR模式下
window is not defined的方案 针对你这种已经有大量组件和依赖、不想逐个修改的情况,这里有几个全局适配的方案,按优先级推荐:
1. 服务端全局模拟window对象
这是最直接的方案,在Node服务端环境中模拟出window及相关浏览器对象,让依赖包在SSR渲染时不会因为找不到window报错。
步骤:
- 在项目根目录创建
plugins/window-mock.js文件:
if (process.server) { // 基础模拟window对象 global.window = {} // 根据依赖需求补充必要的浏览器API,比如document、navigator、localStorage等 global.document = { createElement: () => ({ appendChild: () => {} }), querySelector: () => null, // 可以根据报错信息逐步补充需要的方法 } global.navigator = { userAgent: 'Nuxt SSR Server' } // 如果有依赖用到localStorage,添加模拟实现 global.window.localStorage = { getItem: () => null, setItem: () => {}, removeItem: () => {} } }
- 在
nuxt.config.js的plugins数组最顶部添加这个插件(不要加ssr: false,因为要在服务端执行):
plugins: [ { src: '@/plugins/window-mock.js' }, // 全局mock插件放在最前面 // 你的其他插件保持不变 { src: '@/plugins/antd-ui', ssr: false, mode: 'client' }, { src: '@/plugins/vue2-google-maps', ssr: false, mode: 'client' }, // ... 其余插件 ]
这个方案的好处是不用修改任何组件,只需根据报错信息逐步补充mock的API即可,大部分依赖包只要能检测到window存在就能正常运行。
2. 通过Webpack配置让所有依赖仅在客户端加载
如果有些依赖包在导入阶段就直接访问window(甚至在执行代码前),mock方案可能不够,这时可以通过Webpack的externals配置,让服务端构建时不打包这些依赖,仅在客户端加载它们。
修改nuxt.config.js中的build.extend配置:
build: { // 你的现有配置... transpile: [ 'vue2-google-maps', 'validation', 'vee-validate/dist/rules', 'mask', 'moment', 'chart', 'sortable', ], loaders: { /* ... */ }, vendor: ['vue2-google-maps'], // 添加这个extend配置 extend(config, { isServer }) { if (isServer) { config.externals = [ function(context, request, callback) { // 排除Nuxt核心、Vue、axios等必须在服务端运行的模块 const internalModules = /^(vue|nuxt|@nuxt\/|axios|cookie-universal-nuxt)/ // 匹配所有非本地文件、非内部模块的依赖 if (!internalModules.test(request) && !request.startsWith('.') && !request.startsWith('/')) { // 将这些依赖标记为外部模块,让客户端通过commonjs加载 return callback(null, `commonjs ${request}`) } callback() } ] } } }
这个方案的原理是让服务端构建时跳过第三方依赖的打包,仅在客户端环境中加载并执行这些依赖,从根源避免服务端执行依赖中的window相关代码。
3. 全局使用<client-only>包裹根组件(备选)
如果上面两个方案都无法解决,且你可以接受部分页面失去SSR渲染能力,可以在app.vue中用<client-only>包裹整个Nuxt应用:
<template> <client-only> <Nuxt /> </client-only> </template>
注意:这个方案相当于全局禁用SSR渲染,仅作为最后兜底的选择,会失去SSR的性能和SEO优势。
内容的提问来源于stack exchange,提问作者Ziad Mohamed
相关产品推荐
相关产品推荐

