Angular 服务器端渲染错误消息localStorage is not defined解决分析
作者:JerryWang_汪子熙
TypeScript调用localStorage
在 Angular 应用开发中,我们在 TypeScript 代码里调用 localStorage.
它通过 key 从 local storage 中检索数据。 但是在服务器上,此代码崩溃并显示错误消息:
ReferenceError: localStorage is undefined
在服务器上运行 Angular 应用程序时,全局空间中缺少标准浏览器 API.
例如,在服务器端渲染模式下,开发人员不能像在客户端渲染环境下那样,直接访问全局文档对象。 要获得对文档的引用,必须使用 DOCUMENT 令牌和 Angular 依赖注入机制 DI.
不要通过全局空间使用浏览器 API,而是通过 DI 来替换或禁用浏览器实现,以便在服务器上安全使用这些 API.
参考下面的代码:
import {Component, Inject, NgModule} from '@angular/core'; import {LOCAL_STORAGE} from '@ng-web-apis/common'; @Component({...}) export class SomeComponent { constructor(@Inject(LOCAL_STORAGE) localStorage: Storage) { localStorage.getItem('key'); } }
上面的示例使用来自 @ng-web-apis/common 包的 LOCAL_STORAGE 令牌。
错误分析
但是当我们在服务器上运行这段代码时,我们会得到一个错误。
只需从 AppServerModule 的 providers 中添加来自 @ng-web-apis/universal 包的 UNIVERSAL_LOCAL_STORAGE,并通过令牌 LOCAL_STORAGE,这样就能获得服务器的 localStorage 实现。
import { NgModule } from '@angular/core'; import { ServerModule, } from '@angular/platform-server'; import { AppModule } from './app.module'; import { AppComponent } from './app.component'; import { UNIVERSAL_LOCAL_STORAGE } from '@ng-web-apis/universal'; @NgModule({ imports: [ AppModule, ServerModule, ], providers: [UNIVERSAL_LOCAL_STORAGE], bootstrap: [AppComponent], }) export class AppServerModule {}
看下面这段条件渲染代码:
<> @Component({ selector: 'ram-root', template: '<some-сomp *ngIf="isServer"></some-сomp>', styleUrls: ['./app.component.less'], }) export class AppComponent { isServer = isPlatformServer(this.platformId); constructor(@Inject(PLATFORM_ID) private platformId: Object){} }
这个 Angular Component 需要获取 PLATFORM_ID、目标平台,并了解类的公共属性。此属性将在模板中与 ngIf 指令一起使用。
优雅实现
创建injection token
<> export const IS_SERVER_PLATFORM = new InjectionToken<boolean>('Is server?', { factory() { return isPlatformServer(inject(PLATFORM_ID)); }, });
创建自定义指令
@Directive({ selector: '[ifIsServer]', }) export class IfIsServerDirective { constructor( @Inject(IS_SERVER_PLATFORM) isServer: boolean, templateRef: TemplateRef<any>, viewContainer: ViewContainerRef ) { if (isServer) { viewContainer.createEmbeddedView(templateRef); } } }
然后直接在 Component 上使用这个 structure Directive 就可以了:
<> @Component({ selector: 'ram-root', template: '<some-сomp *ifIsServer"></some-сomp>', styleUrls: ['./app.component.less'], }) export class AppComponent {}
额外的属性已从组件中移除。Component 模板现在更简单了,只用专注于它要实现的业务逻辑。
以上就是Angular 服务器端渲染错误消息localStorage is not defined解决分析的详细内容,更多关于Angular 服务器端渲染错误消息解决的资料请关注脚本之家其它相关文章!