从节点向 angular 通用提供价值
Provide value from node to angular universal
我们有一个 Angular 通用应用程序,当 运行 服务器端时,我们需要将值从 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 is deprecated: from v4.0.0 use Type<T> or InjectionToken<T>
我们尝试将其更改为以便我们使用 InjectionToken (new InjectionToken<TheType>('theKey')
) 或类型而不是字符串,但这不起作用:
Error: StaticInjectorError(AppServerModule)[TheType]:
StaticInjectorError(Platform: core)[TheType]:
NullInjectorError: No provider for TheType!
是否只能通过字符串标记将值从节点传递到angular?
这可以通过提供一个以字符串(用作键)作为值的 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()
修饰它,因为浏览器也会尝试注入令牌(并且由于缺少提供程序而失败)。从节点传递的值只与服务器相关,不需要为 appModule
.
提供 InjectionToken
app.component.ts
constructor(@Optional() @Inject(TOKEN) private token: InjectionToken<TheType>, ...){
if (isPlatformServer(this.platformId)) {
this.theValue = this.injector.get(this.token);
}
}
我必须调整 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);
}
我们有一个 Angular 通用应用程序,当 运行 服务器端时,我们需要将值从 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 is deprecated: from v4.0.0 use Type<T> or InjectionToken<T>
我们尝试将其更改为以便我们使用 InjectionToken (new InjectionToken<TheType>('theKey')
) 或类型而不是字符串,但这不起作用:
Error: StaticInjectorError(AppServerModule)[TheType]: StaticInjectorError(Platform: core)[TheType]: NullInjectorError: No provider for TheType!
是否只能通过字符串标记将值从节点传递到angular?
这可以通过提供一个以字符串(用作键)作为值的 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()
修饰它,因为浏览器也会尝试注入令牌(并且由于缺少提供程序而失败)。从节点传递的值只与服务器相关,不需要为 appModule
.
app.component.ts
constructor(@Optional() @Inject(TOKEN) private token: InjectionToken<TheType>, ...){
if (isPlatformServer(this.platformId)) {
this.theValue = this.injector.get(this.token);
}
}
我必须调整 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);
}