Angular服务端渲染(SSR)运行时出现ReferenceError: window is not defined报错求助
Angular SSR运行
npm run serve:ssr时ReferenceError: window is not defined问题排查与解决 问题背景
使用Angular开发的应用,Web端和SSR构建均成功,但执行npm run serve:ssr时触发以下错误:
ReferenceError: window is not defined
已在server.ts中添加mock-browser相关代码模拟浏览器环境,但问题仍存在,且业务组件未直接使用window对象。
核心原因
报错并非来自业务代码,而是第三方依赖库在服务端渲染阶段直接访问了window对象。Webpack打包SSR产物时会将依赖一同打包,服务端运行时无浏览器环境,导致依赖找不到window而抛出错误。
解决步骤
1. 定位触发错误的第三方依赖
堆栈追踪中的数字模块ID(如18214)无法直接对应依赖,需通过以下方式定位:
- 执行
ng build --ssr --stats-json生成打包统计文件 - 安装
webpack-bundle-analyzer:npm install -D webpack-bundle-analyzer - 运行
npx webpack-bundle-analyzer dist/front/server/stats.json,查看server bundle中各模块对应的依赖包,找到报错模块ID对应的具体依赖。
2. 针对依赖的具体处理方案
方案一:使用依赖的SSR兼容入口
部分库提供专门的服务端适配版本,检查依赖文档,确认是否存在xxx/server或xxx/ssr这类入口,替换原有导入路径。
方案二:通过环境判断隔离浏览器端代码
使用Angular内置的isPlatformBrowser工具,仅在浏览器环境下初始化或导入依赖:
import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-example', templateUrl: './example.component.html' }) export class ExampleComponent implements OnInit { constructor(@Inject(PLATFORM_ID) private platformId: Object) {} ngOnInit(): void { if (isPlatformBrowser(this.platformId)) { // 仅在浏览器端加载依赖 const problematicLib = require('problematic-lib'); problematicLib.init(); } } }
方案三:调整server.ts中mock代码的位置
确保mock代码在导入AppServerModule之前执行,避免依赖先于mock加载:
// 先执行mock代码 (global as any).window = { location: { href: 'http://localhost:4000' }, navigator: { userAgent: 'Angular Universal' } }; (global as any).document = { createElement: () => ({}) }; // 再导入AppServerModule import { AppServerModule } from './src/main.server'; // ...其余server.ts代码
方案四:按需mock而非完整模拟浏览器环境
无需引入mock-browser这类完整的模拟库,仅mock依赖实际需要的window属性即可,减少不必要的环境模拟开销。
额外提醒
使用Angular Universal时,需确保所有第三方依赖均兼容SSR,或已通过上述方式完成环境隔离。若依赖完全不支持SSR,可考虑替换为兼容的替代库。
内容的提问来源于stack exchange,提问作者Nicolas Blaudez
相关产品推荐
相关产品推荐

