如何判断 Spartacus SSR 的 Transfer State 已经正常工作了

发布时间 2023-10-26 15:50:25作者: JerryWang_汪子熙

In the returned index.html , you can check for the script tag, which should by default have an id of ... .

办法就是,在 Chrome 开发者工具 Network 标签页里,查看 script 标签,如果发现具有下列代码片段,说明 Transfer State 机制已经工作了:

<script id="spartacus-app-state" type="application/json">

Transfer State 机制是 Angular 框架中一个关键的概念,用于在服务器端渲染(Server-Side Rendering,SSR)和客户端渲染(Client-Side Rendering,CSR)之间传递数据。这个机制的主要目的是在 SSR 中提高性能和 SEO,同时保持与 CSR 的一致性。

Transfer State 的基本概念

SSR 和 CSR

首先,让我们理解一下 SSR 和 CSR 的基本概念,因为它们是 Transfer State 机制的基础。在 CSR 中,整个应用在浏览器中加载和执行,通过 JavaScript 动态生成内容。这意味着页面的初始加载可能会显示一段空白时间,直到 JavaScript 执行完成。而在 SSR 中,应用的初始 HTML 内容是由服务器渲染的,因此页面在加载时会直接显示内容,而不需要等待 JavaScript 的加载和执行。这提高了性能和 SEO。

客户端与服务器端状态

在一个典型的 Angular 应用中,有许多状态和数据需要在客户端和服务器端之间共享。这包括用户身份验证信息、应用配置、数据等。在 CSR 中,这些数据通常在客户端通过 API 请求获得。但在 SSR 中,为了提高性能,这些数据可以在服务器端就已经准备好并包含在初始 HTML 中,以避免额外的请求。

Transfer State 机制的核心思想是将服务器端生成的状态和数据传输到客户端,以便客户端能够继续使用这些数据而不需要重新获取或计算它们。这可以显著提高应用程序的性能,尤其是对于初次加载。

Transfer State 的工作原理

Transfer State 机制的工作原理可以分为以下几个步骤:

  1. 服务器端渲染(SSR): 当用户访问你的 Angular SSR 应用时,服务器会接收到请求,并执行 Angular 应用的一部分,包括路由和组件。在这个过程中,服务器会获取并生成一些状态和数据,这些数据将在客户端渲染时需要使用。

  2. 数据传输到客户端: 服务器将这些状态和数据存储在一个特殊的 Angular 服务中,称为 TransferState。这个服务充当了服务器端和客户端之间的桥梁,用于在两者之间传递数据。这个服务是一个键值对存储,可以存储各种类型的数据,例如 JSON 对象、字符串等。

  3. HTML 渲染和客户端应用初始化: 服务器继续渲染 Angular 应用的其余部分,并将整个页面的 HTML 生成为响应。这个响应包括一个特殊的标记,用于标识 TransferState 中存储的数据。

  4. 客户端加载: 当用户的浏览器接收到服务器响应后,它会加载 Angular 应用的客户端部分。在客户端初始化过程中,Angular 检测到之前服务器存储的状态标记,并将相关数据从 TransferState 中加载到客户端的内存中。

  5. 客户端继续使用数据: 一旦数据加载到客户端,Angular 应用可以直接使用这些数据,而不需要再次获取它们。这可以加速应用的渲染和交互。

Transfer State 的实现方式

Transfer State 机制的实现方式依赖于 Angular 框架提供的一些核心特性和 API。以下是关键的组件和步骤:

TransferState 服务

TransferState 是 Angular 的一个核心服务,用于存储和传输数据。你可以通过以下代码在你的 Angular 应用中使用它:

import { TransferState, makeStateKey } from '@angular/platform-browser';

// 创建一个状态键
const someDataKey = makeStateKey<any>('someData');

// 存储数据到 TransferState
transferState.set(someDataKey, someData);

// 从 TransferState 获取数据
const data = transferState.get(someDataKey, defaultValue);

上面的代码演示了如何在服务器端将数据存储在 TransferState 中,并在客户端获取它。makeStateKey 用于创建唯一的状态键,以便在两个环境中一致地使用数据。

Angular Universal

Angular Universal 是 Angular 的一个官方扩展,用于支持服务器端渲染。它提供了一些工具和指令,以便在服务器端和客户端之间共享数据。在 Angular Universal 中,你可以使用 TransferState 来实现数据传输。

服务器端数据获取

在服务器端渲染中,通常会使用 Angular Universal 的一些特性来获取数据。这可以包括从数据库、API 或其他外部源获取数据,并将其存储在 TransferState 中,以便在客户端使用。

客户端数据加载

在客户端,Angular 框架会自动检测 TransferState 中的数据,并在初始化应用程序时加载它们。这确保了数据在两个环境中的一致性,而不需要额外的代码来处理数据的传输。

使用 Transfer State 的示例

为了更好地理解 Transfer State 的使用,让我们看一个简单的示例。假设我们有一个 Angular SSR 应用,用于显示博客文章列表。我们想要在服务器端获取博客文章数据,并在客户端加载后立即显示。

服务器端代码

在服务器端,我们可以使用 Angular Universal 来进行数据获取和存储。假设我们有一个 BlogService

来获取博客文章数据:

import { Injectable } from '@angular/core';
import { TransferState } from '@angular/platform-browser';

@Injectable()
export class BlogService {
  constructor(private transferState: TransferState) {}

  getBlogPosts(): Observable<BlogPost[]> {
    const blogPosts = // 获取博客文章数据的逻辑,例如从 API 请求获取
    this.transferState.set<BlogPost[]>('blogPosts', blogPosts);
    return of(blogPosts);
  }
}

在上面的代码中,我们使用 TransferState 来存储博客文章数据,并在客户端加载时提供给应用程序。

客户端代码

在客户端,我们可以使用 TransferState 来获取之前存储的博客文章数据:

import { Component, OnInit } from '@angular/core';
import { TransferState } from '@angular/platform-browser';
import { BlogService } from './blog.service';

@Component({
  selector: 'app-blog',
  templateUrl: './blog.component.html',
})
export class BlogComponent implements OnInit {
  blogPosts: BlogPost[];

  constructor(
    private transferState: TransferState,
    private blogService: BlogService
  ) {}

  ngOnInit() {
    // 尝试从 TransferState 获取博客文章数据
    this.blogPosts = this.transferState.get<BlogPost[]>('blogPosts', []);
    
    // 如果没有从 TransferState 获取到数据,则从服务获取
    if (this.blogPosts.length === 0) {
      this.blogService.getBlogPosts().subscribe((posts) => {
        this.blogPosts = posts;
      });
    }
  }
}

在客户端代码中,我们首先尝试从 TransferState 获取博客文章数据。如果没有从 TransferState 获取到数据,我们可以通过 BlogService 来获取数据,这会在客户端加载后发生。

这个示例展示了如何使用 Transfer State 机制在服务器端和客户端之间传输数据,以提高性能并确保数据的一致性。

Transfer State 的优势和用途

Transfer State 机制在 Angular SSR 应用中具有重要的优势和用途:

  1. 性能提升: 通过在服务器端预取数据并在客户端加载时直接使用它,可以显著提高应用的性能。用户将能够更快地看到内容,并且不需要等待数据加载。

  2. SEO 优化: 搜索引擎爬虫通常能够更容易地索引服务器端渲染的内容,因此使用 SSR 和 Transfer State 可以提高应用的搜索引擎可见性。

  3. 一致性: Transfer State 机制确保了服务器端和客户端之间数据的一致性。这意味着用户在加载后将看到相同的内容,而不会受到异步数据加载的影响。

  4. 用户体验: 减少等待时间和首次加载时间可以改善用户体验,特别是对于慢速网络连接的用户。

  5. 减少服务器负载: 通过在服务器端缓存数据并在客户端加载后使用它,可以减少对服务器的重复请求,降低服务器负载。

结论

Transfer State 机制是 Angular SSR 应用中的一个重要工具,用于在服务器端和客户端之间传输数据,以提高性能和一致性。通过合理使用 TransferState 服务和 Angular Universal,你可以轻松实现数据的传输,改善用户体验,提高搜索引擎可见性,并减少服务器负载。这对于构建高性能的 Angular SSR 应用非常重要,尤其是在要求快速加载和良好的 SEO 的情况下。希望这篇文章能帮助你理解 Transfer State 机制以及如何在你的应用中使用它。