Ada*_*ost 5 express server-side-rendering angular-universal angular angular7
我最近开始将Angular 7.2.0应用程序转换为Angular通用应用程序。该应用程序已成功渲染了服务器端,并在快速的PC和Internet连接上相当快速地传输了状态,但不幸的是,直到交出该页面后,渲染的页面仍缺少通常从API提取的任何数据。
我已将serverURL标记从服务器添加到提供的令牌中,并且在呈现服务器端时,所有http请求均使用完全限定的url进行。但是,这似乎无关紧要,因为所有http调用都在完成之前被取消!我的服务器未显示对api端点的调用,并且客户端记录了错误{}([Error]默认情况下显示为)。
我正在使用TransferStateModule和TransferHttpCacheModule,但是到目前为止,仍然没有任何效果。似乎快速引擎渲染将不会等待异步http调用。它会影响ngOnInit组件的http调用constructor,服务的s以及任何in resolver,因此我不知道如何获取数据。
对于诸如配置数据之类的事情,我将必要的字段作为令牌注入,并在服务器端渲染中检查该令牌,但是我无法对应用程序中的所有数据执行此操作。
以下是我的服务器和应用程序模块的相关部分
app.ts(节点快速服务器)
app.get('*.*', express.static(APP_CONFIG.client_root, {maxAge: 0}));
// Render Angular Universal
if (APP_CONFIG.universal) {
// Our index.html we'll use as our template
const templateFile = HelpersService.tryLoad(join(APP_CONFIG.client_root, './index.html'));
const config = configService.getConfig();
const template = templateFile.toString();
const win = domino.createWindow(template);
const fakeanimation = {
value: () => {
return {
enumerable: true,
configurable: true
};
},
};
global['window'] = win;
global['document'] = {...win.document,
createElement: () => {},
body: {
...win.document.body,
style: {
...win.document.body.style,
transform: fakeanimation,
opacity: fakeanimation,
bottom: fakeanimation,
left: fakeanimation,
}
}
};
global['navigator'] = win.navigator;
global['location'] = win.location;
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('../ssr/ssr.js');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
]
}));
app.set('view engine', 'html');
app.set('views', APP_CONFIG.client_root);
app.get('*', (req, res, next) => {
const protocol = res.locals.protocol || req.protocol;
const showPort = ((APP_CONFIG.port === 80 && protocol === 'http') || (protocol === 'https')) ? false : true;
const serverUrl = `${protocol}://${req.hostname}${showPort ? ':'+APP_CONFIG.port : ''}`;
res.render('index', {
req,
document: template,
url: req.url,
providers: [
{
provide: 'serverURL',
useValue: serverUrl
},
{
provide: 'SERVER_CONFIG',
useValue: config || {}
},
{
provide: 'SERVER_AUTH',
useValue: {signedIn: !!res.locals.auth}
},
]
});
});
}
Run Code Online (Sandbox Code Playgroud)
app.module.ts
@NgModule({
bootstrap: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({appId: 'myapp'}),
BrowserAnimationsModule,
SharedModule,
TransferHttpCacheModule,
BrowserTransferStateModule,
RouterModule.forRoot(
...
Run Code Online (Sandbox Code Playgroud)
app.server.module.ts
@NgModule({
imports: [
// The AppServerModule should import your AppModule followed
// by the ServerModule from @angular/platform-server.
AppModule,
ServerModule,
ServerTransferStateModule,
ModuleMapLoaderModule // <-- *Important* to have lazy-loaded routes work
],
// Since the bootstrapped component is not inherited from your
// imported AppModule, it needs to be repeated here.
bootstrap: [AppComponent],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: ServerSideRequestInterceptor,
multi: true,
},
]
})
export class AppServerModule {}
Run Code Online (Sandbox Code Playgroud)
在ServerSideRequestInterceptor读取serverURL注入令牌,并开始用它预规划的所有要求/。
我觉得我已经很接近破解了,但是我无法告诉我如何让它等待应用程序中的http调用。
编辑:这是我使用通用和角度7制作的回购协议:https : //github.com/swimmadude66/AngularPWASeed/tree/universal7
感谢 @CaerusKaru 在 @nguniversal 问题页面解决了这个问题!https://github.com/angular/universal/issues/1046#issuecomment-455408250
本质上,问题是interceptor我用来将完整的服务器路径附加到 api 调用。它用于Object.assign(request, {url: fullServerUrl});为所有以 开头的 http 请求设置新的 url /。显然,适当的方法是request.clone({url: fullServerUrl});改变一个片段,使数据像急流一样流动。
希望这对其他人有帮助,我将把 repro-repo(很难说和输入)转换成 Angular7 和 Universal 的样板作为工作起点。
| 归档时间: |
|
| 查看次数: |
1163 次 |
| 最近记录: |