Vite SSR预渲染时报错’window is not defined’怎么办?
在用Vite做Vue3的SSR项目时,运行预渲染命令就报错’window is not defined’,但正常渲染页面又没问题。我的组件里用到了window.location,代码是这样的:
// components/Nav.vue
mounted() {
this.currentPath = window.location.pathname
}
我试过在预渲染配置里加server.render参数设置ssrContext,也尝试在setup里用typeof window !== ‘undefined’做环境判断,但预渲染时还是报同样的错。这到底该怎么处理跨环境的window引用呢?
问题出在 mounted 钩子,这个钩子只有在客户端真实 DOM 挂载完成后才会执行,在 SSR 阶段它不会触发。但你用了 window.location,这个属性在 SSR 渲染函数里就被解析了,typeof window 的判断已经来不及了。
解决方案很简单,把 window.location 的引用放到 setup 或 created 里,同时在 setup 里用 process.server 判断:
// components/Nav.vue
或者用 process.server 判断:
created() {
if (process.server) {
// SSR 阶段
return
}
this.currentPath = window.location.pathname
}
这两种方式都能避免 SSR 时访问 window。推荐用 created + typeof window 判断,兼容性更好。
另外你提到的 server.render.ssrContext 设置是用来自定义 SSR 上下文的,这个参数主要用来传递自定义数据,和 window 报错没有直接关系。
这个问题的本质是生命周期差异 + JavaScript 的静态解析机制。当你写 window.location.pathname,JS 引擎在解析时就会标记这个变量依赖,哪怕你用了 typeof window 判断,Vite 的预渲染流程还是会先尝试解析整个模块。
下次遇到类似问题,直接在 SSR 会执行的生命周期里做判断就行了,比如:created、beforeCreate。mounted 和 mounted 之后的钩子在 SSR 时不会执行。