Angular 2+ Universal是否可以从expressjs传递参数(不使用url查询字符串)?

时间:2017-06-01 15:45:57

标签: express angular2-routing angular-universal

我正在使用该示例来设置带有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应用程序?

如何从满负荷的Angular Universal传输更多数据(例如有关用户会话的信息)?

1 个答案:

答案 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
    }
...