允许我们在服务器上运行Angular应用程序的技术在Angular文档中称为Angular Universal。
Angular Universal通过称为服务器端渲染(SSR)的过程在服务器上生成静态应用程序页面。
它可以响应浏览器的请求生成并提供这些页面。 它还可以将Angular模板预先生成为您稍后提供的HTML文件。

普通的Angular应用程序在浏览器中执行,以响应用户操作在DOM中呈现页面。
为了改善用户体验,我们希望呈现页面服务器端并将生成的静态内容发送到客户端,这将确保我们的内容可被搜索引擎抓取,并且还允许具有功能手机的用户使用我们的内容。
在本文中,您将学习如何将Angular Universal支持添加到任何现有的Angular应用中。 让我们从安装依赖开始
服务器端渲染–安装依赖项
为了实现服务器端渲染,我们需要安装一些其他依赖项。
打开终端输入以下命令:
$ npm install --save @angular/platform-server @nguniversal/ module -map-ngfactory-loader ts-loader @nguniversal/express-engine
根AppModule
打开文件src/app/app.module.ts
并在NgModule
元数据中找到BrowserModule
导入。
用该替换该导入:
BrowserModule.withServerTransition({ appId : 'your App-ID' }),
使用以下AppServerModule代码在src/app/
目录中创建一个app.server.module.ts
文件:
import { NgModule } from '@angular/core' ;
import { ServerModule } from '@angular/platform-server' ;
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader' ;
import { AppModule } from './app.module' ;
import { AppComponent } from './app.component' ;
@NgModule({
imports : [
AppModule,
ServerModule,
ModuleMapLoaderModule
],
providers : [
// Add universal-only providers here
],
bootstrap : [ AppComponent ],
})
export class AppServerModule {}
使用以下代码在src目录中创建一个main.server.ts
文件:
// These are important and needed before anything else
import 'zone.js/dist/zone-node' ;
import 'reflect-metadata' ;
import { enableProdMode } from '@angular/core' ;
import * as express from 'express' ;
import { join } from 'path' ;
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const PORT = process.env.PORT || 4000 ;
const DIST_FOLDER = join(process.cwd(), 'dist' );
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require ( './dist/server/main.bundle' );
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine' ;
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader' ;
app.engine( 'html' , ngExpressEngine({
bootstrap : AppServerModuleNgFactory,
providers : [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set( 'view engine' , 'html' );
app.set( 'views' , join(DIST_FOLDER, 'browser' ));
// TODO: implement data requests securely
app.get( '/api/*' , (req, res) => {
res.status( 404 ).send( 'data requests are not supported' );
});
// Server static files from /browser
app.get( '*.*' , express.static(join(DIST_FOLDER, 'browser' )));
// All regular routes use the Universal engine
app.get( '*' , (req, res) => {
res.render(join(DIST_FOLDER, 'browser' , 'index.html' ), { req });
});
// Start up the Node server
app.listen(PORT, () => {
console .log( `Node server listening on http://localhost: ${PORT} ` );
});
提示 :此示例服务器不安全!
在/src
目录中创建tsconfig.server.json
文件,以配置通用应用程序的TypeScript和AOT编译。
{
"extends" : "../tsconfig.json" ,
"compilerOptions" : {
"outDir" : "../out-tsc/app" ,
"baseUrl" : "./" ,
"module" : "commonjs" ,
"types" : []
},
"exclude" : [
"test.ts" ,
"**/*.spec.ts"
],
"angularCompilerOptions" : {
"entryModule" : "app/app.server.module#AppServerModule"
}
}
使用以下代码在项目根目录中创建一个webpack.server.config.js
文件。
const path = require ( 'path' );
const webpack = require ( 'webpack' );
module .exports = {
entry : { server : './server.ts' },
resolve : { extensions : [ '.js' , '.ts' ] },
target : 'node' ,
// this makes sure we include node_modules and other 3rd party libraries
externals: [ /(node_modules|main\..*\.js)/ ],
output : {
path : path.join(__dirname, 'dist' ),
filename : '[name].js'
},
module : {
rules : [{ test : /\.ts$/ , loader : 'ts-loader' }]
},
plugins : [
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580
// for 'WARNING Critical dependency: the request of a dependency is an expression'
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/ ,
path.join(__dirname, 'src' ), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/ ,
path.join(__dirname, 'src' ),
{}
)
]
};
更新.angular-cli.json
应用程序部分
"apps" : [{
"root" : "src" ,
"outDir" : "dist/browser" ,
"assets" : [ "assets" , "favicon.ico" ],
"index" : "index.html" ,
"main" : "main.ts" ,
"polyfills" : "polyfills.ts" ,
"test" : "test.ts" ,
"tsconfig" : "tsconfig.app.json" ,
"testTsconfig" : "tsconfig.spec.json" ,
"prefix" : "app" ,
"styles" : [ "styles.css" ],
"scripts" : [],
"environmentSource" : "environments/environment.ts" ,
"environments" : {
"dev" : "environments/environment.ts" ,
"prod" : "environments/environment.prod.ts"
}
},
{
"platform" : "server" ,
"root" : "src" ,
"outDir" : "dist/server" ,
"assets" : [ "assets" , "favicon.ico" ],
"index" : "index.html" ,
"main" : "main.server.ts" ,
"test" : "test.ts" ,
"tsconfig" : "tsconfig.server.json" ,
"testTsconfig" : "tsconfig.spec.json" ,
"prefix" : "app" ,
"styles" : [ "styles.css" ],
"scripts" : [],
"environmentSource" : "environments/environment.ts" ,
"environments" : {
"dev" : "environments/environment.ts" ,
"prod" : "environments/environment.prod.ts"
}
}
],
通用构建和运行
现在,您已经创建了TypeScript和Webpack配置文件,可以构建并运行Angular Universal应用程序。
首先将build
和serve命令添加到package.json
的scripts部分:
"scripts" : {
...
"build:universal" : "npm run build:client-and-server-bundles && npm run webpack:server" ,
"serve:universal" : "node dist/server.js" ,
"build:client-and-server-bundles" : "ng build --prod && ng build --prod --app 1 --output-hashing=false" ,
"webpack:server" : "webpack --config webpack.server.config.js --progress --colors" ,
...
}
打造通用
在终端中,键入:
npm run build:universal
服务环球
构建应用程序后,启动服务器。
npm run serve:universal
最后。 打开浏览器窗口至http://localhost:4000/
并访问服务器端渲染的Angular应用。
结论
使用服务器端渲染,我们可以保证搜索引擎,与浏览器的Javascript禁用,或没有JavaScript的浏览器仍然可以访问我们的网站内容。
参考文献
- https://codesource.io/build-a-server-monitoring-app-using-node-angular/
先前发布在https://codesource.io/server-side-rendering-in-angular/
From: https://hackernoon.com/server-side-rendering-in-angular-dnf93yup