Vite SSR预渲染时报错’window is not defined’怎么办?

萌新.慧研 阅读 35

在用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引用呢?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
令狐自帅
这问题很常见,SSR渲染流程中 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 时不会执行。
点赞 5
2026-02-06 11:40