我正在使用该示例来设置带有nodejs&的Angular 4 Universal。表达: https://github.com/FrozenPandaz/ng-universal-demo
我一直在尝试将数据从第一个完整页面加载传递到Angular 4最终应用程序。
用例是传输从标题中检测到的语言,以便从Angular 4服务器渲染器中吸收它,以便它可以使用正确的语言进行翻译。
我到目前为止找到的唯一方法是使用来自“/”路由的expressjs的HTTP头进行语言检测,并使用HTTP 302重定向到“/ fr”,例如,如果用户语言是法语。
main.server.ts
app.param('language', function(req: any, res, next, language) {
if(language.length == 2)
{
req.language = language;
next();
} else {
next(new Error('Invalid language found'));
}
});
// Redirect incoming trafic without language in url (302 used so the browser do not seal that redirection if the user decides to change language and reload)
app.get('/', function(req, res) {
res.set('location', baseUrl + '/' + getLanguage(req);
res.status(302).send();
});
routes.ts
export const ROUTES: string[] = [
'/error',
'/:language',
'/:language/download'
];
它有效,因为我能够配置Angular 4路由器并检索当前路由,但它有点脏。
app.module.ts
RouterModule.forRoot([
{ path: '', component: HomeView, pathMatch: 'full'},
{ path: ':language/download', loadChildren: './+lazy/lazy.module#LazyModule'},
{ path: ':language/', redirectTo: ''},
// Catch all if expressjs allowed this url
{ path: '**', component: HomeView }
])
使用Angular Universal,是否有比URL params更好的方法将数据从ExpressJS传递到Angular 4应用程序?
答案 0 :(得分:6)
我遇到了同样的问题,经过几个小时的搜索,我发现了一个适合我的解决方案here。
在您的主页。服务器中'文件,您必须添加' extraProviders'到看起来像这样的aws s3 cp s3://myBucket/myDirectory/todaysFiles/ . --recursive
函数:
app.engine()
然后,您可以访问在' main.server.ts'中定义的提供商。您的Angular4组件或服务代码中的文件如下:
...
let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();
app.engine('html', (_, options, callback) => {
const opts = {
document: template
,url: options.req.url
,extraProviders: [
{ provide: 'host', useFactory: () => options.req.get('host') }
,{ provide: 'PLACEHOLDER', useFactory: () => 'SOME PLACEHOLDER TEXT' }
]
};
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html => callback(null, html));
});
app.set('view engine', 'html');
...
请注意,一旦您的页面加载到客户端浏览器中,主机' -provider将不再可用。相反,你必须从JS api获得主机。
这是我完整的' main.server.ts'文件:
import { Injectable, Injector, PLATFORM_ID } from '@angular/core';
import { isPlatformServer } from '@angular/common';
@Injectable()
export class I18nService {
constructor(
private injector: Injector
,@Inject(PLATFORM_ID) private platformId: Object
){
let host = null;
if (isPlatformServer(this.platformId)) {
// -> server rendered
host = this.injector.get('host');
//do something with host here
} else {
// -> browser rendered
host = document.location...
}
console.log(host);
//do something clever with 'host' here
}
...