Angular 17 SSR集成第三方组件报错window is not defined如何解决?
错误原因是@impactech/sidenav组件在初始化时直接访问了浏览器专属的window对象,但SSR过程在Node.js服务端执行,不存在该对象,因此触发报错。以下是几种可行的解决方法:
方法一:通过环境判断控制组件渲染
利用Angular的isPlatformBrowser工具,仅在浏览器环境下渲染侧边栏组件:
- 修改
app.component.ts:
import { Component, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; import { SideBarComponent, SidebarItemComponent } from '@impactech/sidenav'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, SideBarComponent, SidebarItemComponent], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { isBrowser: boolean; constructor(@Inject(PLATFORM_ID) private platformId: Object) { this.isBrowser = isPlatformBrowser(platformId); } }
- 修改
app.component.html:
<router-outlet> <impactech-sidebar *ngIf="isBrowser"> <impactech-sidebar-item type="header" label="Header"></impactech-sidebar-item> <impactech-sidebar-item label="item without icon" link="#"></impactech-sidebar-item> <impactech-sidebar-item bottom label="item at bottom" link="#" icon="icons8-o-settings"></impactech-sidebar-item> </impactech-sidebar> <router-outlet/>
方法二:动态导入组件(避免服务端解析)
仅在浏览器环境下动态导入组件,彻底避免服务端加载依赖window的代码:
修改app.component.ts:
import { Component, Inject, PLATFORM_ID, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], template: ` <router-outlet> <ng-template #sidebarContainer></ng-template> </router-outlet> `, styleUrl: './app.component.scss' }) export class AppComponent implements OnInit { @ViewChild('sidebarContainer', { read: ViewContainerRef }) sidebarContainer!: ViewContainerRef; isBrowser: boolean; constructor(@Inject(PLATFORM_ID) private platformId: Object) { this.isBrowser = isPlatformBrowser(platformId); } async ngOnInit() { if (this.isBrowser) { const { SideBarComponent, SidebarItemComponent } = await import('@impactech/sidenav'); // 创建侧边栏组件 const sidebarRef = this.sidebarContainer.createComponent(SideBarComponent); // 动态添加子项(示例) const headerItem = sidebarRef.instance.contentContainer.createComponent(SidebarItemComponent); headerItem.instance.type = 'header'; headerItem.instance.label = 'Header'; // 重复上述逻辑添加其他侧边栏项 } } }
方法三:服务端模拟window对象(临时方案,不推荐)
在server.ts顶部添加window模拟,仅适用于库依赖的window属性较少的场景:
(global as any).window = { innerWidth: 1920, innerHeight: 1080 // 根据库的需求补充其他window属性 };
注:此方法可能因属性不全引发其他异常,仅作为临时应急方案。
内容的提问来源于stack exchange,提问作者Sha Na
相关产品推荐
相关产品推荐

