服务器端渲染(Server-Side Rendering,简称SSR)是现代Web开发中的一项重要技术,它允许在服务器上生成HTML页面,然后将这些页面发送给浏览器进行展示。这对于SEO优化、提高首屏加载速度以及改善用户体验都有着显著的好处。Angular Universal 是 Angular 官方提供的 SSR 解决方案,它允许 Angular 应用在服务器端运行并生成静态 HTML 文件。本文将通过具体示例,详细介绍如何使用 Angular Universal 实现 Angular 应用的服务器端渲染,并分享最佳实践。
首先,确保你的开发环境中已经安装了 Node.js 和 npm。接下来,我们将使用 Angular CLI 创建一个新的 Angular 项目:
ng new angular-universal-example
cd angular-universal-example
然后,我们需要安装 Angular Universal 相关的依赖包:
npm install --save @nguniversal/express-engine @nguniversal/module-map-ngfactory-loader
npm install --save-dev @nguniversal/builders
@nguniversal/express-engine
用于在 Express 服务器中渲染 Angular 应用,@nguniversal/module-map-ngfactory-loader
用于加载 Angular 组件工厂,而 @nguniversal/builders
提供了 Angular CLI 插件来支持 SSR 构建。
接下来,配置 Angular CLI 使用 Angular Universal 进行 SSR 构建。编辑 angular.json
文件,添加 server
和 prerender
任务:
"architect": {
"build": {
},
"serve": {
},
"server": {
"builder": "@nguniversal/builders:webpack",
"options": {
"project": "angular-universal-example-server"
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"prerender": {
"builder": "@nguniversal/nextjs-craftsman:prerender",
"options": {
"routes": ["/", "/about"]
},
"dependencies": ["server"]
}
}
这里我们定义了两个新的目标:server
用于构建服务器端应用,prerender
用于预渲染静态页面。
接下来,创建服务器端应用。在项目根目录下运行以下命令:
ng generate @nguniversal:server --project=angular-universal-example
这将生成一个名为 angular-universal-example-server
的项目,并在 projects
文件夹下创建服务器端代码。
现在,我们需要设置一个 Express 服务器来托管和渲染 Angular 应用。在项目根目录下创建一个名为 server.ts
的文件,并添加以下内容:
import 'reflect-metadata';
import * as express from 'express';
import {
join } from 'path';
import {
AppServerModuleNgFactory, LAZY_MODULE_MAP } from './dist/server/main';
import {
renderModuleFactory } from '@angular/platform-express';
import {
provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
async function bootstrap() {
const app = express();
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', (_, options, callback) => {
renderModuleFactory(AppServerModuleNgFactory, {
document: options.req.rawHeaders[1],
url: options.req.url,
// The bootstrap mechanism for Angular apps
extraProviders: [provideModuleMap(LAZY_MODULE_MAP)]
}).then(html => {
callback(null, html);
});
});
app.set('view engine', 'html');
app.set('views', join(process.cwd(), 'dist/browser'));
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { /* ... */ });
// Serve static files from /browser
app.get('*.*', express.static(join(process.cwd(), 'dist/browser')));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', {
req });
});
// Start up the Node server
app.listen(process.env.PORT || 4000);
console.log(`Node Express server listening on http://localhost:${
process.env.PORT || 4000}`);
}
bootstrap();
这段代码设置了一个 Express 服务器,并使用 renderModuleFactory
来渲染 Angular 应用。我们还设置了静态文件服务,以便客户端 JavaScript 文件和其他资源可以从浏览器目录中提供。
最后,构建并启动服务器:
ng run angular-universal-example:server --prod
这将构建服务器端应用,并生成 dist/server
目录下的文件。然后,你可以通过运行 node dist/server/main.js
来启动服务器。
通过上述步骤,我们成功地将 Angular 应用转换为了支持服务器端渲染的形式。这种方法不仅提高了应用的性能,还增强了搜索引擎的友好性。希望本文提供的代码示例和实践指南能够帮助你在实际项目中更好地应用 Angular Universal 技术,提升应用的用户体验。