我编写了一个角度应用程序,但出现错误:
“错误参考错误:本地存储未定义”
我只是在本地存储服务中使用:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class LocalStorageService {
constructor() {}
setItem(key: string, value: string) {
localStorage.setItem(key, value);
}
getItem(key: string) {
return localStorage.getItem(key);
}
}
我写了一个拦截器:
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { LocalStorageService } from '../services/local-storage-service.service';
import { Injectable } from '@angular/core';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private localStorageService: LocalStorageService) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
let token = this.localStorageService.getItem('token');
let newRequest: HttpRequest<any>;
newRequest = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + token),
});
return next.handle(newRequest);
}
}
我在 app.module 中添加了这一行:
providers: [{provide:HTTP_INTERCEPTORS,useClass:AuthInterceptor,multi:true},provideClientHydration()],
如何解决这个问题?
我安装了这个 npm 包:localstorage-polyfill 并添加了这 2 行
import 'localstorage-polyfill'
global['localStorage'] = localStorage;
所以我的 server.ts 像这样:
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import AppServerModule from './src/main.server';
import 'localstorage-polyfill'
global['localStorage'] = localStorage;
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');
const indexHtml = join(serverDistFolder, 'index.server.html');
const commonEngine = new CommonEngine();
server.set('view engine', 'html');
server.set('views', browserDistFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(browserDistFolder, {
maxAge: '1y'
}));
// All regular routes use the Angular engine
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap: AppServerModule,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
return server;
}
function run(): void {
const port = process.env['PORT'] || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
run();
但是问题还是一样。
试试这个:
//LocalStorageService
constructor(@Inject(PLATFORM_ID) platformId: object) {}
setItem(key: string, value: string) {
if (isPlatformBrowser(platformId)) {
localStorage.setItem(key, value);
}
}
getItem(key: string) {
if (isPlatformBrowser(platformId)) {
return localStorage.getItem(key);
}
return null;
}
问题是,当你使用 SSR 时,你必须验证浏览器是否使用窗口相关对象,有很多方法可以做到这一点(例如使用 domino 进行检查),我给你的例子是一个非常简单的例子,但它可以工作。
另一种方法是为 localStorage 提供一个工厂,并验证是否是PlatformBrowser,如果不是,你可以返回一个模拟的 localStorage。