Mic*_*lix 6 express angular2-routing angular-universal
我正在使用该示例使用nodejs和expressjs设置Angular 4 Universal:https: //github.com/FrozenPandaz/ng-universal-demo
我一直在尝试将数据从第一个完整页面加载传递到Angular 4 final应用程序.
用例是传输从标题中检测到的语言,以便从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();
});
Run Code Online (Sandbox Code Playgroud)
routes.ts
export const ROUTES: string[] = [
'/error',
'/:language',
'/:language/download'
];
Run Code Online (Sandbox Code Playgroud)
它工作,因为我能够配置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 }
])
Run Code Online (Sandbox Code Playgroud)
有没有比URL params更好的方法使用Angular Universal将数据从ExpressJS传递到Angular 4应用程序?
我有同样的问题,几个小时的搜索后,我发现,是为我工作的解决方案在这里.
在'main.server.ts'文件中,你必须将'extraProviders'添加到app.engine()看起来像这样的函数中:
...
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');
...
Run Code Online (Sandbox Code Playgroud)
然后,您可以访问Angular4组件或服务代码中'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
}
...
Run Code Online (Sandbox Code Playgroud)
请注意,一旦您的页面加载到客户端浏览器中,"主机"提供商将不再可用.相反,你必须从JS api获得主机.
这是我完整的'main.server.ts'文件:
import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { platformServer, renderModuleFactory } from '@angular/platform-server'
import { enableProdMode } from '@angular/core'
import { AppServerModuleNgFactory } from '../dist/ngfactory/src/app/app.server.module.ngfactory'
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';
import * as compression from 'compression';
const PORT = 4200;
enableProdMode();
const app = express();
let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();
app.engine('html', (_, options, callback) => {
const opts = {
document: template
,url: options.req.url
,extraProviders: [
{ provide: 'request', useFactory: () => options.req }
,{ provide: 'host', useFactory: () => options.req.get('host') }
]
};
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html => callback(null, html));
});
app.set('view engine', 'html');
app.set('views', 'src');
app.use(compression());
app.get('*.*', express.static(join(__dirname, '..', 'dist')));
app.get('*', (req, res) => {
res.render('index', { req });
});
app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1488 次 |
| 最近记录: |