使用Angular5进行服务器端渲染(从AngularJS迁移)

Ale*_*lls 7 angularjs angular5

我们正在将我们的应用程序从AngularJS转换为Angular5.我试图弄清楚如何使用Angular5复制一些行为 - 即使用服务器端渲染来创建可注入值.

在我们当前的Angular1.6应用程序中,我们有这个index.hbs文件:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Collaborative Tool</title>
  <link href="favicon.ico" rel="shortcut icon" type="image/x-icon">
</head>

<body class="aui content" ng-app="app">

  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>

  <script>

    /* globals angular */
    angular.module('app')
      .value('USER', JSON.parse('{{{user}}}'))
      .value('WORKSTREAM_ENUM', JSON.parse('{{{workStreamEnum}}}'))
      .value('CATEGORY_ENUM', JSON.parse('{{{categoryEnum}}}'))
      .value('ROLES_ENUM', JSON.parse('{{{roles}}}'))
      .value('FUNCTIONAL_TEAM_ENUM', JSON.parse('{{{functionalTeams}}}'))
      .value('CDT_ENV', '{{CDT_ENV}}')
      .value('CDT_HOST', '{{CDT_HOST}}')
      .value('CDT_LOGOUT_URL', '{{CDT_LOGOUT_URL}}');


  </script>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

所以我们做的是在第一个脚本标签中加载角度,然后使用第二个脚本标签创建一些值/枚举/常量.基本上使用服务器端渲染(把手)将数据发送到前端.

我的问题:有没有办法用Angular5做一些非常相似的事情? 我们如何使用服务器端渲染在Angular5中创建可注入的模块/值?

Dan*_*pel 4

我的团队在从 AngularJS 过渡到 Angular(v2 的早期发布候选版本)时也遇到了同样的问题。我们提出了一个仍在使用的解决方案,我不知道有任何更新可以使它变得更容易(至少在不使用 Angular Universal 时 - 如果您使用它,那么有内置的东西可以引导初始数据)。我们通过序列化 JSON 对象并将其设置为 HTML 中应用程序根 Angular 组件上的属性,将数据传递到 Angular 应用程序:

<app-root [configuration]="JSON_SERIALIZED_OBJECT"></app-root>
Run Code Online (Sandbox Code Playgroud)

其中JSON_SERIALIZED_OBJECT是实际的序列化对象。我们使用 .NET(非 Core,因此 Angular Universal 并不是真正的选择)来渲染我们的页面(正在执行[configuration]="@JsonConvert.SerializeObject(Model.Context)"),因此不知道您需要做什么,但看起来您应该能够做同样的事情您之前已将其序列化。

设置完成后,我们必须JSON.parse(...)在主应用程序组件中手动操作该对象,但我们将其视为 Angular 输入。这就是我们的组件抓取的样子:

import { Component, ElementRef } from '@angular/core';
import { ConfigurationService } from 'app/core';

@Component(...)
export class AppComponent {
    constructor(private element: ElementRef, private configurationService: ConfigurationService) {
        this.setupConfiguration();
    }

    private setupConfiguration() {
        const value = this.getAttributeValue('[configuration]');
        const configuration = value ? JSON.parse(value) : {};

        this.configurationService.setConfiguration(configuration);
    }

    private getAttributeValue(attribute: string) {
        const element = this.element.nativeElement;

        return element.hasAttribute(attribute) ? element.getAttribute(attribute) : null;
    }
}
Run Code Online (Sandbox Code Playgroud)

如图所示,我们使用服务来共享系统中的数据。它可以像这样简单:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { Configuration } from './configuration.model';

@Injectable()
export class ConfigurationService {
    private readonly configurationSubject$ = new BehaviorSubject<Configuration>(null);
    readonly configuration$ = this.configurationSubject$.asObservable();

    setConfiguration(configuration: Configuration) {
        this.configurationSubject$.next(configuration);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在需要配置数据的组件中,我们注入此服务并观察更改。

import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/takeUntil';

import { ConfigurationService } from 'app/core';

@Component(...)
export class ExampleThemedComponent implements OnDestroy {
    private readonly destroy$ = new Subject<boolean>();

    readonly theme$: Observable<string> = this.configurationService.configuration$
        .takeUntil(this.destroy$.asObservable())
        .map(c => c.theme);

    constructor(private configurationService: ConfigurationService) {
    }

    ngOnDestroy() {
        this.destroy$.next(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我们有时会在运行时更改配置,这就是我们使用主题和可观察量的原因。如果您的配置不会更改,那么您可以跳过这些示例的所有该部分。