关于前端:使用-Angular-Universal-进行服务器端渲染的防御性编程思路

2次阅读

共计 2273 个字符,预计需要花费 6 分钟才能阅读完成。

如果无奈从 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 是打算反对或更新版本反对的性能的补丁。

正文完
 0