关于“深入浅析Angular SSR”的完整攻略,下面是详细的讲解:
什么是Angular SSR
Angular SSR(Server-Side Rendering)是指在服务端执行Angular应用程序并生成HTML响应的过程。通俗的说,就是在服务端预渲染且构造HTML并且在传回浏览器渲染时设置完整的、原始的HTML文档。这样可以提高应用程序的首次加载速度和搜索引擎优化(SEO)。
Angular SSR的优势
相对于客户端渲染(CSR)的应用程序来说,Angular SSR具有以下优势:
- 更快的首次加载性能:因为HTML文档在服务端已经构造完毕,所以用户在浏览器中首次打开应用程序时可以更快地看到页面内容
- 更好的SEO表现:由于预渲染的HTML文档包含所有的页面内容,搜索引擎可以更好地识别和索引这些内容
Angular SSR的实现方式
Angular应用程序的SSR实现需要在服务器端使用Node.js进行构建。具体的步骤如下:
- 安装Angular Universal
Angular Universal是Angular官方的SSR库,可以帮助我们构建Angular应用程序的服务端版本。
npm install @angular/platform-server @angular/platform-browser-dynamic @angular/common --save
npm install @nguniversal/express-engine --save
- 创建服务端入口文件
需要在项目根目录下创建一个服务端入口文件,例如server.ts
。需要注意的是,服务端入口文件需要引入Angular应用程序的AppModule,并把它作为参数传到ngExpressEngine()
方法中进行渲染。
import 'zone.js/dist/zone-node';
import * as express from 'express';
import { join } from 'path';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { AppServerModule } from './src/main.server';
const app = express();
const port = 4000;
const distFolder = join(process.cwd(), 'dist/angular-ssr-demo/browser');
const indexHtml = require('fs').readFileSync(join(distFolder, 'index.html'), 'utf8');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
app.set('view engine', 'html');
app.set('views', distFolder);
app.get('*.*', express.static(distFolder));
app.get('*', (req, res) => {
res.render('index', { req, res, providers: [] , document: indexHtml});
});
app.listen(port, () => {
console.log(`Node server listening on http://localhost:${port}`);
});
- 修改Angular应用程序的入口文件
需要在Angular应用程序的入口文件(通常是main.ts
或app.module.ts
)中添加以下代码,用于将应用程序构建成双端应用程序:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { environment } from './environments/environment';
import { AppBrowserModule } from './app/app.browser.module';
import { AppServerModule } from './app/app.server.module';
if (environment.production) {
enableProdMode();
}
const boot = () => platformBrowserDynamic().bootstrapModule(AppBrowserModule);
if (environment.production) {
document.addEventListener('DOMContentLoaded', () => {
boot();
});
} else {
platformBrowserDynamic().bootstrapModule(AppServerModule)
.then(platformRef => {
// The Server app is bootstrapped asynchronously so we need to wait
// for that to complete before adding our Components
const instance = platformRef.injector.get(HttpServerOperations).getServer();
instance.get('*', (req, res) => {
platformRef.bootstrapModule(AppBrowserModule).then(() =>
ngExpressEngine({ req, res, bootstrap: AppBrowserModule, document: readFileSync(join(DIST_FOLDER, 'browser', 'index.html'), 'utf8') })(req, res));
});
}).catch(err => console.log(err));
}
- 构建和运行应用程序
使用以下命令构建应用程序并生成服务端代码:
ng build --prod && ng run angular-ssr-demo:server
使用node dist/angular-ssr-demo\server.js
命令来启动服务端应用程序。
示例说明
下面是两个Angular SSR的示例:
示例1:服务端渲染数据
在常规的CSR应用程序中,数据通常是异步加载的。但是在SSR应用程序中,我们需要在预渲染HTML文档中包含这些数据。以下是如何在Angular SSR应用程序中实现:
- 首先,我们需要在服务端使用Node.js获取异步数据。可以使用Angular的
HttpClient
类来实现这一点。 - 其次,我们需要将此数据通过一个服务暴露给客户端Angular应用程序。可以使用Angular的
TransferHttpCacheModule
和ServerTransferStateModule
来实现这一点。 - 然后,我们需要在客户端Angular应用程序中使用
TransferState
服务来获取服务器端传递的数据并存储在客户端的状态树中。
以下是一个基本的数据服务的代码示例:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { isPlatformServer } from '@angular/common';
const DATA_KEY = makeStateKey<any>('data');
@Injectable()
export class DataService {
private data: any;
constructor(private http: HttpClient, private state: TransferState) {}
getData(): Observable<any> {
if (isPlatformServer(this.platformId)) {
return this.http.get('/api/data').pipe(
tap(data => this.state.set(DATA_KEY, data))
);
} else {
if (this.data) {
return of(this.data);
} else {
const data = this.state.get(DATA_KEY, null);
if (data) {
this.data = data;
this.state.remove(DATA_KEY);
return of(this.data);
} else {
return this.http.get('/api/data').pipe(
tap(data => (this.data = data))
);
}
}
}
}
}
示例2:使用缓存优化SSR应用
在SSR应用程序中,我们需要采用不同的方法来处理缓存。与CSR应用程序不同,每个请求都需要生成一个新的HTML文档,这会严重影响性能。为了避免这种情况,我们可以使用缓存来存储预渲染的HTML文档,并在下一次请求时重新使用它。
以下是一个简单的缓存实现示例:
import { Injectable } from '@angular/core';
@Injectable()
export class CacheService {
private cache = {};
get(key: string) {
return this.cache[key];
}
set(key: string, value: any) {
this.cache[key] = value;
}
}
在服务端入口文件中,可以使用此服务来检查是否有可用的预渲染HTML文档,并在没有可用的情况下生成新的HTML文档:
app.get('*', (req, res) => {
const url = req.url;
const cacheKey = url;
const cachedHtml = cacheService.get(cacheKey);
if (cachedHtml) {
res.send(cachedHtml);
return;
}
res.render('index', { req, res, providers: [
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
{ provide: 'REQUEST', useValue: req },
provideModuleMap(lazyModuleMap),
], document: indexHtml})
.then(html => {
cacheService.set(cacheKey, html);
res.send(html);
})
.catch(err => {
console.error(err);
res.sendStatus(500);
});
});
以上就是关于“深入浅析Angular SSR”的完整攻略,包含了实现方式和两个示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入浅析Angular SSR - Python技术站