2017-06-01 26 views
5

我使用例如設置角4與通用的NodeJS & expressjs: https://github.com/FrozenPandaz/ng-universal-demoAngular 2+ Universal可以從expressjs傳遞參數(不使用url查詢字符串)?

我一直在試圖從第一個完整的頁面加載數據傳遞到角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' 
]; 

它的工作原理,因爲我能夠配置角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 } 
    ]) 

難道還有比網址參數更好的方法來從ExpressJS數據傳遞給採用了棱角分明的通用角4應用程序?

如何從一個滿載的Angular Universal傳輸更多數據(例如關於用戶會話的信息)?

+0

你找到一個解決辦法?我有同樣的問題。 –

回答

2

我有同樣的問題,經過幾個小時的搜索,我發現一個解決方案,爲我工作here

你在「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'); 
... 

然後,您可以訪問您在已定義的供應商在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 
    } 
... 

請注意,一旦您的網頁客戶端,瀏覽器加載了「host'提供商將不更久可用。相反,你必須從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}!`); 
}); 
相關問題