【问题标题】:Provide value from node to angular universal提供从节点到角度通用的值
【发布时间】:2020-07-01 21:04:19
【问题描述】:

我们有一个 Angular Universal 应用程序,我们需要在运行服务器端时将值从 node.js 传递给 angular。我们通过在 server.ts 中使用以下代码解决了这个问题:

const theValue: TheType = nodeLogicToRetrieveValue();

app.engine('html', (_, options, callback) => {
  let engine = ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
      provideModuleMap(LAZY_MODULE_MAP),
      { provide: 'theKey', useFactory: () => theValue, deps: [] }
    ]
  });
  engine(_, <any>options, callback)
});

在组件中,我们使用以下代码解析该对象:

if (isPlatformServer(this.platformId)) {
  this.theValue = this.injector.get('theKey');
}

这很好用,但是 linting 会发出以下警告:

get 已弃用:从 v4.0.0 开始使用 Type 或 InjectionToken

我们尝试将其更改为使用 InjectionToken (new InjectionToken&lt;TheType&gt;('theKey')) 或类型而不是字符串,但这不起作用:

错误:StaticInjectorError(AppServerModule)[TheType]: StaticInjectorError(平台:核心)[TheType]: NullInjectorError:没有 TheType 的提供者!

是否只能通过字符串标记将值从节点传递到角度?

【问题讨论】:

    标签: node.js angular angular-universal server-side-rendering


    【解决方案1】:

    可以通过提供带有字符串(用作键)作为值的 InjectionToken 来完成。 InjectionToken 可以输入TheType,lint 不会给出警告。

    在单独的文件中创建 InjectionToken 以避免循环依赖。

    tokens.ts

    export const TOKEN = new InjectionToken<TheType>('theKey');
    

    在 appServerModule 中提供 InjectionToken。

    app.server.module.ts

    providers: [
        ....
        { provide: TOKEN, useValue: 'theKey', deps: [] }
    ]
    

    注入令牌并用@Optional() 装饰它,因为浏览器也会尝试注入令牌(由于缺少提供程序而失败)。从node传过来的值只和服务端相关,appModule不需要提供InjectionToken。

    app.component.ts

    constructor(@Optional() @Inject(TOKEN) private token: InjectionToken<TheType>, ...){
        if (isPlatformServer(this.platformId)) {
           this.theValue = this.injector.get(this.token);
        }
    }
    

    【讨论】:

      【解决方案2】:

      我不得不调整 Emil 的答案以使其正常工作(我使用的是 angular 10)。

      定义令牌:

      export const CLIENT_ID = new InjectionToken<string>('client-id');
      

      提供来自服务器的值:

      app.engine('html', ngExpressEngine({
          bootstrap: AppServerModule,
          providers: [
            {
              provide: CLIENT_ID,
              useValue: 'MyClientId',
            },
          ],
        }) as any);
      

      在客户端注入值:

      constructor(@Optional() @Inject(CLIENT_ID) private clientId: string){
        console.log(this.clientId);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-09
        • 2019-09-07
        • 1970-01-01
        • 2017-04-28
        • 2016-10-29
        • 2014-10-31
        • 2022-10-20
        相关资源
        最近更新 更多