How to judge that the Transfer State of Spartacus SSR is working properly

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

The way is to check the script tag in the Network tab of Chrome Developer Tools. If you find the following code snippet, it means that the Transfer State mechanism is already working:

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

The Transfer State mechanism is a key concept in the Angular framework, used to transfer data between server-side rendering (Server-Side Rendering, SSR) and client-side rendering (Client-Side Rendering, CSR). The main purpose of this mechanism is to improve performance and SEO in SSR while maintaining consistency with CSR.

Basic concepts of Transfer State

SSR and CSR

First, let us understand the basic concepts of SSR and CSR, as they are the basis of the Transfer State mechanism. In CSR, the entire application is loaded and executed in the browser, with content dynamically generated via JavaScript. This means that the initial load of the page may appear blank for a period of time until the JavaScript execution is complete. In SSR, the initial HTML content of the application is rendered by the server, so the content will be displayed directly when the page is loaded, without waiting for JavaScript to be loaded and executed. This improves performance and SEO.

Client and server status

In a typical Angular application, there is a lot of state and data that needs to be shared between the client and server. This includes user authentication information, application configuration, data, etc. In a CSR, this data is typically obtained on the client side via an API request. But in SSR, to improve performance, this data can be prepared on the server side and included in the initial HTML to avoid additional requests.

The core idea of the Transfer State mechanism is to transfer state and data generated on the server side to the client so that the client can continue to use these data without re-acquiring or calculating them. This can significantly improve the performance of your application, especially for initial loading.

How Transfer State works

The working principle of the Transfer State mechanism can be divided into the following steps:

  1. Server Side Rendering (SSR): When a user accesses your Angular SSR application, the server receives the request and executes a portion of the Angular application, including routes and components. During this process, the server will obtain and generate some status and data, which will be used when rendering on the client side.

  2. Data transfer to client: The server stores this state and data in a special Angular service called TransferState. This service acts as a bridge between the server and the client, passing data between the two. This service is a key-value store that can store various types of data, such as JSON objects, strings, etc.

  3. HTML Rendering and Client App Initialization: The server continues rendering the rest of the Angular app and generates the entire page’s HTML as a response. This response includes a special tag that identifies the data stored in TransferState.

  4. Client-side loading: When the user’s browser receives the server response, it loads the client-side portion of the Angular app. During client initialization, Angular detects the state tokens previously stored by the server and loads the relevant data from TransferState into the client’s memory.

  5. Client continues to use data: Once the data is loaded to the client, Angular applications can use the data directly without needing to fetch them again. This speeds up your app’s rendering and interactions.

How to implement Transfer State

The implementation of the Transfer State mechanism relies on some core features and APIs provided by the Angular framework. Here are the key components and steps:

TransferState Service

TransferState is a core service of Angular for storing and transferring data. You can use it in your Angular app with the following code:

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

//Create a status key
const someDataKey = makeStateKey<any>('someData');

// Store data in TransferState
transferState.set(someDataKey, someData);

// Get data from TransferState
const data = transferState.get(someDataKey, defaultValue);

The code above demonstrates how to store data in TransferState on the server side and get it on the client side. makeStateKey is used to create a unique state key so that data can be used consistently in both environments.

Angular Universal

Angular Universal is an official extension of Angular to support server-side rendering. It provides tools and instructions to share data between server and client. In Angular Universal, you can use TransferState to implement data transfer.

Server-side data acquisition

In server-side rendering, some features of Angular Universal are usually used to obtain data. This can include getting data from a database, API, or other external source and storing it in TransferState for use on the client side.

Client data loading

On the client side, the Angular framework automatically detects the data in TransferState and loads them when initializing the application. This ensures data consistency in both environments without requiring additional code to handle the transfer of data.

Example of using Transfer State

To better understand the use of Transfer State, let’s look at a simple example. Let’s say we have an Angular SSR app that displays a list of blog posts. We want to get the blog post data on the server side and display it as soon as it loads on the client side.

Server-side code

On the server side, we can use Angular Universal for data retrieval and storage. Suppose we have a BlogService

To get blog post data:

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

@Injectable()
export class BlogService {<!-- -->
  constructor(private transferState: TransferState) {<!-- -->}

  getBlogPosts(): Observable<BlogPost[]> {<!-- -->
    const blogPosts = // Logic to obtain blog post data, such as from API request
    this.transferState.set<BlogPost[]>('blogPosts', blogPosts);
    return of(blogPosts);
  }
}

In the code above, we use TransferState to store the blog post data and provide it to the application when the client loads.

Client code

On the client side, we can use TransferState to get previously stored blog post data:

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() {<!-- -->
    //Try to get blog post data from TransferState
    this.blogPosts = this.transferState.get<BlogPost[]>('blogPosts', []);
    
    // If no data is obtained from TransferState, obtain it from the service
    if (this.blogPosts.length === 0) {<!-- -->
      this.blogService.getBlogPosts().subscribe((posts) => {<!-- -->
        this.blogPosts = posts;
      });
    }
  }
}

In the client code, we first try to get the blog post data from TransferState. If the data is not obtained from TransferState, we can obtain the data through BlogService, which will happen after the client is loaded.

This example shows how to use the Transfer State mechanism to transfer data between the server and client to improve performance and ensure data consistency.

Advantages and uses of Transfer State

The Transfer State mechanism has important advantages and uses in Angular SSR applications:

  1. Performance improvements: By prefetching data on the server side and using it directly when loading on the client side, you can significantly improve your application’s performance. Users will be able to see content faster and won’t need to wait for data to load.

  2. SEO Optimization: Search engine crawlers can often index server-side rendered content more easily, so using SSR and Transfer State can improve your app’s search engine visibility.

  3. Consistency: The Transfer State mechanism ensures data consistency between the server and the client. This means users will see the same content after loading without being affected by asynchronous data loading.

  4. User experience: Reducing wait times and first load times can improve user experience, especially for users on slow network connections.

  5. Reduce server load: By caching data on the server side and using it after loading on the client side, you can reduce repeated requests to the server and reduce server load.

Conclusion

The Transfer State mechanism is an important tool in Angular SSR applications, used to transfer data between the server and client to improve performance and consistency. By properly using the TransferState service and Angular Universal, you can easily transfer data, improve user experience, increase search engine visibility, and reduce server load. This is very important for building high-performance Angular SSR applications, especially when fast loading and good SEO are required. I hope this article helped you understand the Transfer State mechanism and how to use it in your application.