Angular 17出现localStorage未定义,如何不关闭SSR解决该问题?
Angular 17 SSR环境下使用localStorage的替代方案
Angular 16升级到17后开启SSR时出现localStorage is not defined错误,本质原因是SSR在Node.js服务端执行,而服务端环境不存在浏览器的localStorage对象。不用关闭SSR的话,可以试试以下几种方案:
1. 手动判断执行环境,仅在浏览器端访问localStorage
利用Angular内置的isPlatformBrowser工具函数,区分服务端和浏览器环境,只在浏览器里调用localStorage:
import { Inject, Injectable, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Injectable({ providedIn: 'root' }) export class StorageService { constructor(@Inject(PLATFORM_ID) private platformId: Object) {} setItem(key: string, value: string): void { if (isPlatformBrowser(this.platformId)) { localStorage.setItem(key, value); } } getItem(key: string): string | null { if (isPlatformBrowser(this.platformId)) { return localStorage.getItem(key); } return null; } }
服务端渲染时会跳过localStorage相关逻辑,自然不会触发错误。
2. 用TransferState同步服务端数据到客户端
如果需要在服务端渲染时先处理数据,再同步到客户端localStorage,可以用Angular的TransferState实现前后端数据传递:
import { Inject, Injectable, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser, isPlatformServer } from '@angular/common'; import { TransferState, makeStateKey } from '@angular/platform-browser'; const STORAGE_KEY = makeStateKey<Record<string, string>>('app-storage'); @Injectable({ providedIn: 'root' }) export class StorageService { constructor( @Inject(PLATFORM_ID) private platformId: Object, private transferState: TransferState ) {} setItem(key: string, value: string): void { if (isPlatformBrowser(this.platformId)) { localStorage.setItem(key, value); } else if (isPlatformServer(this.platformId)) { const existing = this.transferState.get(STORAGE_KEY, {}); this.transferState.set(STORAGE_KEY, { ...existing, [key]: value }); } } getItem(key: string): string | null { if (isPlatformBrowser(this.platformId)) { // 先把服务端传递的数据同步到localStorage const serverData = this.transferState.get(STORAGE_KEY, {}); if (serverData[key]) { localStorage.setItem(key, serverData[key]); this.transferState.remove(STORAGE_KEY); } return localStorage.getItem(key); } else if (isPlatformServer(this.platformId)) { const serverData = this.transferState.get(STORAGE_KEY, {}); return serverData[key] || null; } return null; } }
服务端把临时数据存在TransferState,客户端初始化时会自动读取这些数据并同步到localStorage,既避免服务端报错,又保证前后端数据一致。
3. 使用第三方兼容库
直接用专门适配Angular SSR的存储库,比如ngx-webstorage,它内部已经处理了环境兼容逻辑,不用自己写判断:
首先安装依赖:
npm install ngx-webstorage
然后封装使用:
import { Injectable } from '@angular/core'; import { LocalStorageService } from 'ngx-webstorage'; @Injectable({ providedIn: 'root' }) export class AppStorageService { constructor(private localStorage: LocalStorageService) {} setItem(key: string, value: string): void { this.localStorage.store(key, value); } getItem(key: string): string | null { return this.localStorage.retrieve(key); } }
内容的提问来源于stack exchange,提问作者prashant kushwah
相关产品推荐
相关产品推荐

