Вы не можете получить доступ к REQUEST
в браузере, это объект на стороне сервера, переданный из expressjs
в ng-universal
.Так что в худшем случае ваш код должен сделать что-то вроде
constructor(
@Inject(PLATFORM_ID) private platformId,
@Optional() @Inject(REQUEST) private request
) {
doSomethingWithRequestIfServer();
}
someOtherMethod() {
doSomethingWithRequestIfServer();
}
doSomethingWithRequestIfServer() {
if (isPlatformServer(this.platformId)) {
// should see this in stdout of node process, or wherever node logs
console.log('rendering server side for request:', req);
/* use req */
} else {
// browser console should print null
console.log('working browser side, request should be null', req);
}
}
Тогда, когда в браузере ваше приложение не будет смотреть на Request, тогда как при рендеринге на стороне сервера, будет.То есть, ваш серверный рендеринг будет запускать ваше угловое приложение один раз , в результате этого HTML-код будет отправлен в браузер.Затем браузер снова загрузит приложение Angular и заберет , откуда завершится рендеринг сервера.
В лучшем случае, чтобы избежать if
s и проверок платформы, я бы предложил расположить ваш макетприложение, так что ваш код на стороне сервера предоставляется только на стороне сервера, а код на стороне браузера предоставляется в браузере.Это определенно потребует больше кода, но будет более прямым с точки зрения обслуживания.(быстрый ввод текста обезьяны ниже)
Общее объявление интерфейса
// common.ts
export abstract class MyServiceBase {
abstract doSomething(): void;
}
// if implementations of service will be provided only in Angular implementation, InjectionToken can be used.
export const MY_SERVICE = new InjectionToken<MyServiceBase>('MY_SERVICE');
// otherwise, if server side implementation will be injected by from node process, then should be string only. (For alternative illustrated below in the end).
// export const MY_SERVICE = 'MY_SERVICE';
Общий компонент приложения, который должен отображаться как на сервере, так и в браузере.
// app.component.ts
@Component({
// skipped
})
export class AppComponent {
constructor(@Inject(MY_SERVICE) myService: MyServiceBase) {
myService.doSomething();
}
}
Общий код приложения, которыйприменимо как для сервера, так и для браузера.
// app.module.ts
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
// app-browser.service.ts
@Injectable()
export class MyServiceForBrowser extends MyServiceBase {
constructor() {
console.log('MyService browser implementation');
}
doSomthing(): void {
// do something meaningful in browser
}
}
Загрузите это вместо стандартного AppModule
для отделения обеспечения реализации.
// app-browser.module.ts
@NgModule({
imports: [AppModule],
providers: [{provide: MY_SERVICE, useClass: MyServiceForBrowser}],
bootstrap: [AppComponent]
})
export class AppBrowserModule {
}
Серверная часть от углового приложения Если вы можете сразу реализовать функции на стороне сервера в приложении Angular, тогда.
// app-server.service.ts
@Injectable()
export class MyServiceForServer extends MyServiceBase {
constructor(@Inject(REQUEST) private request) {
console.log('MyService server implementation');
}
doSomthing(): void {
// do something meaningful on server
console.log('request is', this.request);
}
}
Модуль на стороне сервера для начальной загрузки с ngExpressEngine
.
// app-server.module.ts
@NgModule({
imports: [AppModule],
providers: [{provide: MY_SERVICE, useClass: MyServiceForServer}],
bootstrap: [AppComponent]
})
export class AppServerModule {}
Альтернативный серверсторона от сервера
В качестве альтернативы, MyServiceForServer
может быть даже предоставлено из кода сервера.В этом случае нет необходимости предоставлять реализацию в угловой реализации:
// app-server.module.ts
@NgModule({
imports: [AppModule],
bootstrap: [AppComponent]
})
export class AppServerModule {}
Вместо этого запишите его как обычный код на стороне сервера:
export class MyServiceForServer extends MyService {
constructor(private request) {
console.log('MyService server implementation');
}
doSomthing(): void {
// do something meaningful on server
console.log('request is', this.request);
}
}
И введите как external
значение:
app.get('*', (req: Request, res) => {
// construct the server side service instance
const myService = new MyServiceForServer(req);
// render server side with service instance provided
res.render(join(DIST_FOLDER, 'browser', 'index.html'), {
providers: [{provide: MY_SERVICE, useValue: myService}],
req
});
});
В этом случае убедитесь, что ваш токен MY_SERVICE
представляет собой простую строку, а не экземпляр InjectionToken
.