2017-06-20 126 views

回答

3

在给定教程中提到的示例使用的是Angular Resources部分中提到的示例。他们最近更新了他们的文档,并且还没有提供详细的文档来实现@ angular/universal。 This曾经是你正在寻找的页面,但它提到了一些问题here。可能这就是为什么他们删除它并决定重写它。

13

Angular Universal仅供角2.如果你想从头开始,你可以使用这个Angular 4 Universal Seed它具有像所有的特点:

  • 角4
  • 的WebPack
  • 开发/生产模式
  • SCSS编译
  • 国际化,搜索引擎优化,并TSLint/codelyzer
  • 延迟加载,配置,缓存

或者,如果你已经有角4项目运行,您可以通过在代码中做如下设置集成通用:

安装这些软件包:
npm install @angular/{common,compiler,compiler-cli,core,forms,http,platform-browser,platform-browser-dynamic,platform-server,router,animations}@latest [email protected] --save

npm install express @types/express --save-dev

中添加这是你的app.module.ts文件

import { BrowserModule } from '@angular/platform-browser'; 
BrowserModule.withServerTransition({ 
    appId: 'my-app-id' // withServerTransition is available only in Angular 4 
}), 

创建以下文件

的src/UNI/app.server.ts

import { NgModule } from '@angular/core'; 
import { APP_BASE_HREF } from '@angular/common'; 
import { ServerModule } from '@angular/platform-server'; 
import { AppComponent } from '../app/app'; 
import { AppModule } from '../app/app.module'; 
import 'reflect-metadata'; 
import 'zone.js'; 
@NgModule({ 
    imports: [ 
    ServerModule, 
    AppModule 
    ], 
    bootstrap: [ 
    AppComponent 
    ], 
    providers: [ 
    {provide: APP_BASE_HREF, useValue: '/'} 
    ] 
}) 
export class AppServerModule { 
} 


的src/UNI /服务器uni.ts

import 'zone.js/dist/zone-node'; 
import 'zone.js'; 
import 'reflect-metadata'; 
import { enableProdMode } from '@angular/core'; 
import { AppServerModuleNgFactory } from '../../aot/src/uni/app.server.ngfactory'; 
import * as express from 'express'; 
import { ngUniversalEngine } from './universal-engine'; 
enableProdMode(); 
const server = express(); 
// set our angular engine as the handler for html files, so it will be used to render them. 
server.engine('html', ngUniversalEngine({ 
    bootstrap: [AppServerModuleNgFactory] 
})); 
// set default view directory 
server.set('views', 'src'); 
// handle requests for routes in the app. ngExpressEngine does the rendering. 
server.get(['/', '/dashboard', '/heroes', '/detail/:id'], (req:any, res:any) => { 
    res.render('index.html', {req}); 
}); 
// handle requests for static files 
server.get(['/*.js', '/*.css'], (req:any, res:any, next:any) => { 
    let fileName: string = req.originalUrl; 
    console.log(fileName); 
    let root = fileName.startsWith('/node_modules/') ? '.' : 'src'; 
    res.sendFile(fileName, { root: root }, function (err:any) { 
     if (err) { 
      next(err); 
     } 
    }); 
}); 
// start the server 
server.listen(3200,() => { 
    console.log('listening on port 3200...'); 
}); 

的src/uni/universal-engine.ts

import * as fs from 'fs'; 
import { renderModuleFactory } from '@angular/platform-server'; 
const templateCache = {}; // cache for page templates 
const outputCache = {}; // cache for rendered pages 
export function ngUniversalEngine(setupOptions: any) { 
    return function (filePath: string, options: { req: Request }, callback: (err: Error, html: string) => void) { 
    let url: string = options.req.url; 
    let html: string = outputCache[url]; 
    if (html) { 
     // return already-built page for this url 
     console.log('from cache: ' + url); 
     callback(null, html); 
     return; 
    } 
    console.log('building: ' + url); 
    if (!templateCache[filePath]) { 
     let file = fs.readFileSync(filePath); 
     templateCache[filePath] = file.toString(); 
    } 
    // render the page via angular platform-server 
    let appModuleFactory = setupOptions.bootstrap[0]; 
    renderModuleFactory(appModuleFactory, { 
     document: templateCache[filePath], 
     url: url 
    }).then(str => { 
     outputCache[url] = str; 
     callback(null, str); 
    }); 
    }; 
} 

添加下面的配置在tsconfig.ts文件我假设位于根目录

{ 
    "compilerOptions": { 
     "baseUrl": "", 
     "declaration": false, 
     "emitDecoratorMetadata": true, 
     "experimentalDecorators": true, 
     "lib": ["es2016", "dom"], 
     "moduleResolution": "node", 
     "outDir": "./dist/out-tsc", 
     "sourceMap": true, 
     "target": "es5", 
     "module": "commonjs", 
     "types": ["node"], 
     "typeRoots": [ 
      "node_modules/@types" 
     ] 
    }, 
    "files": [ 
     "src/uni/app.server.ts", 
     "src/uni/server-uni.ts" 
    ], 
    "angularCompilerOptions": { 
     "genDir": "aot", 
     "entryModule": "./src/app/app.module#AppModule", 
     "skipMetadataEmit": true 
    }, 
    "exclude": [ 
     "test.ts", 
     "**/*.spec.ts" 
    ] 
} 

Atlast您webpack.config.uni.js在根目录

const ngtools = require('@ngtools/webpack'); 
const webpack = require('webpack'); 
const path = require('path'); 
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin"); 
module.exports = { 
    devtool: 'source-map', 
    entry: { 
     main: ['./src/uni/app.server.ts', './src/uni/server-uni.ts'] 
    }, 
    resolve: { 
     extensions: ['.ts', '.js'] 
    }, 
    target: 'node', 
    output: { 
     path: path.join(__dirname, "dist"), 
     filename: 'server.js' 
    }, 
    plugins: [ 
     new ngtools.AotPlugin({ 
      tsConfigPath: './tsconfig.json' 
     }) 
    ], 
    module: { 
     rules: [ 
      { 
       test: /\.(scss|html|png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
       use: 'raw-loader' 
      }, 
      { test: /\.ts$/, loader: require.resolve('@ngtools/webpack') }, 
      { 
       test: /\.(png|jpg|woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 
       loader: 'url?limit=512&&name=[path][name].[ext]?[hash]' 
      }, 
      { test: /\.scss$/, use: [{ 
       loader: "style-loader" // creates style nodes from JS strings 
      }, { 
       loader: "css-loader" // translates CSS into CommonJS 
      }, { 
       loader: "sass-loader" // compiles Sass to CSS 
      }] } 
     ] 
    } 
} 

添加以下脚本包。JSON文件:

"ngc-build": "ngc -p ./tsconfig.json", // To generate ngFactory file 
"build:uni": "webpack --config webpack.config.uni.js", 
"serve:uni": "node dist/server.js", 

有一些事情,我们应该牢记:

  • windowdocumentnavigator和其他浏览器的类型 - 不存在于服务器上 - 这样使用它们,或者任何使用它们的库(例如jQuery)都不起作用。如果您确实需要某些功能,则您在此选项中提供了一些选项link
1

你可以找到服务器端的角度4教程用的WebPack渲染this blog

特点:

  • 它是在建角4
  • 它不依赖于角CLI
  • 它是建立在的WebPack
  • 博客中提供了三个阶段一步步指令:
    • 阶段1:在Docker容器上运行服务器端渲染的Hello World页面(我为您的Docker容器提供了一个预先安装的Docker镜像方便,但说明应该对自己的角环境)
    • 第2阶段的工作:在主页创建一个新的功能链接
    • 阶段3(可选):通过动态的RESTful API插入一个WordPress博客文章
  • (dockerhost)$ docker run -it -p 8002:8000 oveits/angular_hello_world:centos bash 
    (container)# git clone https://github.com/oveits/ng-universal-demo 
    (container)# cd ng-universal-demo 
    (container)# npm i 
    (container)# npm run start 
    

    我所选择的端口8002的上方,因为我在端口8000上运行的其他例子:

最终的结果可以很容易地一个泊坞主机上像如下观察和8001已经;如果docker主机在Virtualbox上运行,则可能需要从Virtualbox主机的8002到Virtualbox VM的8002之间的端口映射。

在浏览器上,导航至http://localhost:8002/blog。您将看到从Wordpress API下载的博客文章的内容。用右键单击 - >查看源文件您将看到HTML内容。这表明这是一个服务器端呈现的页面。

PS:好像你已经尝试了教程,教程是基于Git project that originally has been created by Rob Wormald,但this fork by FrozenPandaz,我发现升级到角4,并与的WebPack更好地工作(见the blog附录版本更多细节)。

相关问题