深入浅析Angular SSR

关于“深入浅析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进行构建。具体的步骤如下:

  1. 安装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
  1. 创建服务端入口文件

需要在项目根目录下创建一个服务端入口文件,例如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}`);
});
  1. 修改Angular应用程序的入口文件

需要在Angular应用程序的入口文件(通常是main.tsapp.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));

}
  1. 构建和运行应用程序

使用以下命令构建应用程序并生成服务端代码:

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的TransferHttpCacheModuleServerTransferStateModule来实现这一点。
  • 然后,我们需要在客户端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技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • Navigator sendBeacon页面关闭也能发送请求方法示例

    Navigator.sendBeacon()是一个异步方法,用于在浏览器后台向服务器发送小量数据。通常,该方法在页面关闭时使用,以确保在离开页面前将相关数据传输到服务器。该方法可以将数据发送到服务器,即使页面已关闭或卸载。 下面是使用sendBeacon()方法的完整攻略: 1. 定义数据 定义要传递的数据。可以使用FormData或JSON等格式。 con…

    JavaScript 2023年6月11日
    00
  • js中string之正则表达式replace方法详解

    JS中String之正则表达式replace方法详解 什么是正则表达式 正则表达式可以理解为是一种匹配文本模式的规则。使用正则表达式可以方便地进行文本操作,如查找、替换、匹配等。在JavaScript中,可以使用RegExp对象来表示正则表达式。 replace方法概述 字符串的replace()方法可以用来替换字符串中的文本。它可以接受两个参数,第一个参数…

    JavaScript 2023年5月28日
    00
  • JS操作JSON方法总结(推荐)

    JS操作JSON方法总结(推荐) 什么是JSON JSON全称是JavaScript Object Notation,即JavaScript对象表示法。在Web应用程序中,使用JSON格式来交换数据是一种常见方式。JSON是一种轻量级的数据交换格式,容易被阅读和编写,并且易于机器解析和生成。JSON是一种文本格式,可以通过JavaScript或其他语言解析。…

    JavaScript 2023年5月27日
    00
  • javascript实现鼠标点击页面 移动DIV

    实现鼠标点击页面移动DIV可以通过JavaScript来完成,这需要监听鼠标的事件,在事件中获取鼠标的坐标位置,然后动态修改DIV元素的位置。下面是完整的实现攻略: 监听鼠标事件 通过addEventListener方法,可以为页面添加鼠标事件监听器,捕获鼠标事件并在事件处理程序中处理。下面是一个简单的示例代码: document.addEventListe…

    JavaScript 2023年6月11日
    00
  • Android studio 混淆配置详解

    Android Studio 混淆配置详解 什么是混淆? 混淆(Proguard)是 Android 应用程序构建工具中的一个开源的代码缩减、优化和混淆工具。在编译 APK 文件的过程中,代码混淆可以将类名、方法名、变量名等一些敏感信息混淆成一个无法识别的字符串,以增加代码的安全性和减小 APK 大小。 如何进行混淆? 在 Android Studio 中进…

    JavaScript 2023年6月10日
    00
  • 教你用js截取字符串开头、结尾及两字符串之间的内容

    教你用JS截取字符串开头、结尾及两字符串之间的内容 在JS中,截取字符串是非常常见的一个操作,本文将为大家介绍如何用JS截取字符串的操作,并提供两个示例。 一、截取字符串的基本用法 JS提供了substr和slice两种方法来截取字符串,不同的是它们的参数使用方式不同。 1. substr 它接受两个参数,第一个参数是开始截取的位置,第二个参数是截取的长度。…

    JavaScript 2023年5月28日
    00
  • JS数组方法some、every和find的使用详情

    JS数组方法some、every和find的使用详情 在 JavaScript 中,数组是一种常用的数据结构类型,而对于数组的操作,有三种常用的数组方法,它们分别是 some、every 和 find,本文将详细讲解它们的使用方法。 some方法 some 方法用于判断目标数组中是否存在至少一个元素满足指定的条件,如果满足则返回 true,如果不满足则返回 …

    JavaScript 2023年5月27日
    00
  • JS内部事件机制之单线程原理

    JS内部事件机制是指JavaScript在运行时的一种消息传递机制。其基本原理是采用单线程模型,即所有的任务都在同一个线程中执行,并且采用事件循环的机制来管理和调度任务。以下是JS内部事件机制之单线程原理的完整攻略: 什么是JS内部事件机制? JS内部事件机制是指JavaScript运行时的一种机制,用于管理和调度任务,其原理是采用单线程模型,即所有的任务都…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部