我也会提供我在这里找到的解决方案。我还在 Angular Universal 的 Github 存储库中以 issue 的形式发布了它。如果对 Universal 进行了更改,这将使这更容易,我会更新这个答案。
解决方案:
基本上我现在所做的,是在 Angular 应用程序完全启动之前,在服务器和应用程序中获取有关页面的数据。在路由器进行初始导航之前,更改app-routing.modules-constructor 中的routes-array 显然已经足够早地获取动态路由了。
看起来或多或少是这样的(正如 Nicolae 所说,这可以重构以避免重复代码):
server.ts:
server.get('*', (req, res) => {
// fetch dynamic routes
// /!\ duplicate code to src/main.ts
fetch('http://static.content/')
.then(response => response.json())
.then(resp => {
const routes = resp.entries.map(route => ({
path: route.path,
component: StaticContentComponent,
data: {
id: route._id,
name: route.name
}
}));
res.render(indexHtml, {
req,
providers: [
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
{ provide: DYNAMIC_ROUTES, useValue: routes }
]
});
});
});
return server;
}
和main.ts基本一样:
document.addEventListener('DOMContentLoaded', () => {
// fetch dynamic routes
// /!\ duplicate code to server.ts
fetch('http://static.content/')
.then(response => response.json())
.then(resp => {
const routes = resp.entries.map(route => ({
path: route.path,
component: StaticContentComponent,
data: {
id: route._id,
name: route.name
}
}));
platformBrowserDynamic([
{ provide: DYNAMIC_ROUTES, useValue: routes }
])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
});
然后在我的app-routing.module.ts 中,我将DYNAMIC_ROUTES 中提供的数据添加到路由中:
const DYNAMIC_ROUTES = new InjectionToken<IEnvironment>('dynamicRoutes');
@NgModule({
imports: [
RouterModule.forRoot(routes, {
initialNavigation: 'enabled'
})
],
exports: [RouterModule]
})
export class AppRoutingModule {
constructor(@Inject(DYNAMIC_ROUTES) private dynamicRoutes, private router: Router) {
const config = router.config;
config.unshift(...this.dynamicRoutes);
this.router.resetConfig(config);
}
}