使用 Angular Universal 进行服务器端渲染的防御性编程思路
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 Angular Universal 进行服务器端渲染的防御性编程思路相关的知识,希望对你有一定的参考价值。
如果无法从 Angular 平台注入所需的正确全局值,则可以避免调用浏览器代码,只要不需要在服务器上访问该代码即可。 例如,全局窗口元素的调用通常是为了获取窗口大小或其他一些视觉方面。 但是,在服务器上,没有 screen 的概念,所以很少需要这个功能。
开发人员可能会在网上和其他地方阅读到推荐的方法是使用 isPlatformBrowser 或 isPlatformServer,这个指导值得商榷。
这是因为这样做的话,最终会在应用程序代码中创建特定于平台的代码分支。 这不仅不必要地增加了应用程序的大小,而且还增加了必须维护的复杂性。 通过将代码分离到单独的特定于平台的模块和实现中,基本代码可以保留业务逻辑,并且特定于平台的异常将按应有的方式处理:在个案抽象的基础上。 这可以使用 Angular 的依赖注入 (DI) 来完成,以便在运行时删除有问题的代码并放入替换代码。
下面是一个例子。
为浏览器环境和服务器环境分别创建不同的 service 类:
// window-service.ts
import Injectable from @angular/core;
@Injectable()
export class WindowService
getWidth(): number
return window.innerWidth;
// server-window.service.ts
import Injectable from @angular/core;
import WindowService from ./window.service;
@Injectable()
export class ServerWindowService extends WindowService
getWidth(): number
return 0;
在服务器端 module 里,使用 Angular 注入框架,注入 ServiceWindowService 实现:
// app-server.module.ts
import NgModule from @angular/core;
import WindowService from ./window.service;
import ServerWindowService from ./server-window.service;
@NgModule(
providers: [
provide: WindowService,
useClass: ServerWindowService,
]
)
如果第三方提供的组件不是开箱即用的通用兼容组件,则除了基本应用程序模块之外,您还可以为浏览器和服务器(您应该已经拥有的服务器模块)创建两个单独的模块。 基本应用程序模块将包含所有与平台无关的代码,浏览器模块将包含所有特定于浏览器/服务器不兼容的代码,反之亦然用于服务器模块。 为了避免编辑过多的模板代码,您可以创建一个空操作组件以插入库组件。 这是一个例子:
// example.component.ts
import Component from @angular/core;
@Component(
selector: example-component,
template: `<library-component></library-component>`, // this is provided by a third-party lib
// that causes issues rendering on Universal
)
export class ExampleComponent
app module:
// app.module.ts
import NgModule from @angular/core;
import ExampleComponent from ./example.component;
@NgModule(
declarations: [ExampleComponent],
)
浏览器端 module:
// browser-app.module.ts
import NgModule from @angular/core;
import LibraryModule from some-lib;
import AppModule from ./app.module;
@NgModule(
imports: [AppModule, LibraryModule],
)
// library-shim.component.ts
import Component from @angular/core;
@Component(
selector: library-component,
template: ,
)
export class LibraryShimComponent
服务器端 module:
// server.app.module.ts
import NgModule from @angular/core;
import LibraryShimComponent from ./library-shim.component;
import AppModule from ./app.module;
@NgModule(
imports: [AppModule],
declarations: [LibraryShimComponent],
)
export class ServerAppModule
shim 是针对特定平台永远不支持的功能的补丁。polyfill 是计划支持或更新版本支持的功能的补丁。
以上是关于使用 Angular Universal 进行服务器端渲染的防御性编程思路的主要内容,如果未能解决你的问题,请参考以下文章
使用Angular4(Angular Universal)的服务器端渲染[关闭]
Angular 2 Universal - 使用手写笔和 pug 模板的服务器端渲染
使用 JWT 对 Angular Universal 进行身份验证
使用 Angular Universal 在服务器端运行时找不到模块环境