使用 angular-cli 在通用渲染中使用 cookie
Posted
技术标签:
【中文标题】使用 angular-cli 在通用渲染中使用 cookie【英文标题】:Using cookies in Universal Rendering using angular-cli 【发布时间】:2018-01-26 18:12:42 【问题描述】:我使用 angular-cli 制作了一个 Angular 应用程序,并按照给定的here 的步骤在其中进行了通用渲染。但有人提到,如果我正在做通用渲染,我不能在我的应用程序中使用窗口和文档等全局变量,我如何在前端设置 cookie 以维护用户会话。以前我使用的是 JWT,但为此我需要在浏览器中设置 cookie。
【问题讨论】:
【参考方案1】:注意:以下所有信息仅在您使用带有 Express 的 Node 来动态呈现(在请求到达服务器时)您的 Angular 应用程序时才有效在服务器上。我还没有研究预渲染。我不知道如果你使用 Express 以外的框架,比如 Hapi 或其他任何其他框架,你会怎么做。我只能猜测@nguniversal
也应该为这些人提供解决方案,但还没有研究过。
话虽如此,以下是我刚刚设法在我的应用程序中提供 cookie 的方式,当它在服务器端呈现时:
app.server.module.ts
:
// ...
import Request from 'express';
import REQUEST from '@nguniversal/express-engine/tokens';
@Injectable()
export class RequestCookies
constructor(@Inject(REQUEST) private request: Request)
get cookies()
return !!this.request.headers.cookie ? this.request.headers.cookie : null;
@NgModule(
imports: [
// ...
],
providers: [
CookieService,
provide: 'req', useClass: RequestCookies
],
bootstrap: [AppComponent]
)
export class AppServerModule
app.module.ts
:(有些人可能称之为app.browser.module.ts
)
@NgModule(
declarations: [
// ...
],
imports: [
// ...
],
providers: [
CookieService,
provide: 'req',
useValue: null
],
bootstrap: [AppComponent]
)
export class AppModule
cookie.service.ts
:
import Inject, Injectable from '@angular/core';
@Injectable()
export class CookieService
private cookieStore = ;
constructor(
@Inject('req') private readonly req: any,
)
if (this.req !== null)
this.parseCookies(this.req.cookies);
else
this.parseCookies(document.cookie);
public parseCookies(cookies)
this.cookieStore = ;
if (!!cookies === false) return;
let cookiesArr = cookies.split(';');
for (const cookie of cookiesArr)
const cookieArr = cookie.split('=');
this.cookieStore[cookieArr[0]] = cookieArr[1];
get(key: string)
return !!this.cookieStore[key] ? this.cookieStore[key] : null;
any.component.ts
:
// ...
constructor(
private cookieService: CookieService
)
needMyCookie()
const userCookie = this.cookieService.get('user');
确保你> npm install express @nguniversal/express-engine
附:我首先查看了这个 repo:https://github.com/angular/universal-starter/tree/master/cli 用于服务器端渲染,我自己只做了 cookie 部分(不包括在那里)。 该回购遵循您链接中的普遍故事,但超出了范围。如果您只是遵循普遍的故事,它会说:
暂不支持延迟加载
但是,如果您尝试我提供链接的 repo,您会发现延迟加载的模块也在服务器上被渲染!不知道关键是什么,可能和server.js
文件和@nguniversal/module-map-ngfactory-loader
中的代码有关
我已经尝试过: CLI 版本 1.4.2 和 Angular 版本:4.4.1
这是我在浏览器中禁用 javascript 后得到的结果:
我的轮播项目是这样间隔的,因为它们实际上已缩放到 90%。我在 onInit 中的项目上有一个 zoomIn 动画。在服务器渲染视图上,我将它们强制设置为 90%,这样它们在第一次加载时不会以 100% 显示,然后在客户端启动后,让它们以 90 到 100 的动画速度显示。
此外,如果有人遇到此答案并注意到屏幕截图中对视口宽度的引用,在主导航链接下方的代码块中 - 如果他们想知道 - 这是我的WindowService
:
import Injectable, PLATFORM_ID, Inject from '@angular/core';
import isPlatformBrowser, isPlatformServer from '@angular/common';
@Injectable()
export class WindowService
constructor(
@Inject(PLATFORM_ID) private readonly platformId: any,
)
get width()
if (isPlatformBrowser(this.platformId))
return window.innerWidth;
else
return 'Not available server-side!';
// return null;
只需将其添加到app.module.ts
和app.server.module.ts
中的providers: []
数组即可。
这里需要注意的另一件事是我将Node与Express一起使用。如果您使用其他框架,例如 Hapi 或其他任何其他框架,我不知道这样做。
【讨论】:
不错的实现,但我收到错误:InjectionToken REQUEST 没有提供者你对此有什么想法吗? @OkanAslankan 您在某处可以公开访问代码吗?就我而言,它仍然像我在上面发布的代码一样工作。唯一的区别是我将@Injectable()
装饰器添加到RequestCookies
类中(我也更新了答案)......但除非你想直接将该类注入另一个服务,否则不需要这样做,而且我认为错误听起来会有所不同。
另外,您可以查看这个示例,也许它会有所帮助:github.com/patrickmichalina/fusebox-angular-universal-starter/… 浏览 Patrick 的示例也帮助了我几次,并意识到了一些我什至没有想到的事情。
我通过在构造函数中手动注入它来解决它。在 github 上看到了一些关于这个问题的问题。谢谢
我试过了,还是不行,这里是repo github.com/intergleam/universal-starter/tree/…【参考方案2】:
我已经成功使用了 npm 包 ng2-cache(我使用的是 Angular 4,它工作得很好)。我正在使用本地存储,所以我将它放在我的模块提供程序数组中,如下所示:
providers: [
CacheService,
provide: CacheStorageAbstract, useClass: CacheLocalStorage,
...
]
另一种选择是使用 isPlatformBrowser(),如 here 所示。
最丑陋的选择是将处理 cookie 的代码放在 try-catch 语句中。这样它就可以在浏览器上运行,而在服务器端被忽略。
【讨论】:
就我个人而言,我还没有尝试过 ng2-cache。但我认为忽略服务器端的 cookie 不应该是一种选择。大多数情况下,我们需要从 cookie 中获取至少一个令牌,以便在来自服务器的第一个渲染中获得授权和/或显示基于用户的数据。 那么目前认证令牌的选项是什么? 自从之前提出这个问题以来,服务器端渲染已经大大扩展。有许多文档化的解决方案说明如何使其工作,但这实际上取决于您的堆栈。 能否请您修改github.com/angular/universal-starter 以显示如何使用cookie?以上是关于使用 angular-cli 在通用渲染中使用 cookie的主要内容,如果未能解决你的问题,请参考以下文章
您必须在 angular-cli 项目中才能在重新安装 angular-cli 后使用 build 命令