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

Angular12执行serve:ssr报错ReferenceError: window is not defined如何解决?

问题核心原因&对应解决方案

1. 首要修复:调整global挂载逻辑的执行顺序

你当前server.ts里的代码顺序完全错误:所有import导入语句在JavaScript/TypeScript中会被自动提升到文件最顶部执行,你现在是先导入了AppServerModule等业务模块,之后才给global挂载window对象。如果模块顶层代码(包括你依赖的第三方包的顶层代码)存在对window的直接调用,导入时就会触发报错,后面的挂载逻辑完全不会生效。
修复步骤:

  • 新增src/global-patch.ts文件,把你当前所有domino初始化、global属性挂载的逻辑全部移到这个文件中:
const domino = require('domino');
const fs = require('fs');
const path = require('path');
const distFolder = path.join(process.cwd(), 'dist/treo/browser');
const template = fs.readFileSync(path.join(distFolder, 'index.html')).toString();
const win = domino.createWindow(template);

(global as any).window = win;
(global as any).document = win.document;
(global as any).DOMTokenList = win.DOMTokenList;
(global as any).Node = win.Node;
(global as any).Text = win.Text;
(global as any).HTMLElement = win.HTMLElement;
(global as any).navigator = win.navigator;
(global as any).WebSocket = require('ws');
(global as any).XMLHttpRequest = require('xhr2');
  • 在server.ts的第一行引入这个补丁文件,再写其他导入逻辑:
import './src/global-patch';
// 后面再写其他所有import代码
import { ngExpressEngine } from '@nguniversal/express-engine';
// ...剩余原有逻辑

2. 排查第三方依赖的window调用

你自己的业务代码没有直接调用window,不代表第三方依赖没有这类逻辑:很多前端库(比如图表库、UI组件、工具库)会直接在顶层作用域访问window,不会等到运行时再判断环境。
修复方案:

  • 开启服务端调试定位报错源:修改package.json里的serve:ssr命令,加调试参数:node --inspect dist/treo/server/main.js,打开Chrome访问chrome://inspect即可抓取完整报错栈,直接定位是哪个依赖触发的问题。
  • 对触发问题的依赖做特殊处理:
    • 如果是你业务代码中引入的依赖,不要在文件顶部静态导入,改用动态导入仅在浏览器环境加载:
    if(isPlatformBrowser(this.platformId)) {
      import('xxx-library').then(lib => {
        // 执行相关逻辑
      })
    }
    
    • 如果是组件库的组件触发问题,在服务端模块(app.server.module.ts)中用空占位组件替换该组件,避免服务端渲染时执行。

3. 检查业务代码的顶层window调用

排查你所有业务代码文件中,是否存在不在类/函数内部的顶层window调用,比如:

// 这种顶层代码导入时就会执行,服务端直接报错
const screenWidth = window.innerWidth;

@Component({
  // 装饰器内如果用到window也会直接报错
  host: { '[style.width.px]': window.innerWidth }
})

这类逻辑要全部移入方法内部,包裹isPlatformBrowser判断。

4. 补全WindowRef的服务端实现

你当前的WindowRef服务默认可能仅在浏览器环境返回正确对象,需要在app.server.module.ts的providers数组中新增服务端的实现:

providers: [
  {
    provide: WindowRef,
    useValue: { nativeWindow: (global as any).window }
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:36:00