Skip to content

Angular SSR - Stop Your HTTP Cache from Vanishing During Hydration

Updated: at 09:41 PM

Table of contents

Open Table of contents

TLDR

When using Angular SSR with different origins between server and client (e.g. your-internal-endpoint.internal vs your-public-exposed-endpoint.com), HTTP state is lost during hydration. The HTTP_TRANSFER_CACHE_ORIGIN_MAP token lets you map these origins, preserving HTTP cache state and preventing duplicate requests, therefore you don’t have a flickering effect when you handling different states, like loading. Configure it in your app.config.ts to maintain state consistency across server and client environment.

The problem

When it comes to hydration process, you can set up very promising feature, that makes your app not performing additional requests when hydration is enabled. By that we will avoid also some additional flickering.

export const appConfig: ApplicationConfig = {
  providers: [provideClientHydration(withHttpTransferCacheOptions({}))],
};

In some scenarios, it will work, but in major use cases it won’t work as expected and we will still have double request on our page. Why? Because we have different endpoint on server and on client in most cases!

Understanding API Endpoint Differences

When hydration mechanism starts, it checks if the endpoints are same, if they’re not, it will perform the request anyway during hydration. That can cause us aditional flickering because application state may change during making another call - for example from loading to loaded.

What’s the fix for that?

Actually, it’s not popular token (I found it accidentally during watching some docs in IDE), but IMHO it’s yet must have for most of the SSR apps. Usage of this token:

export const appConfigServer: ApplicationConfig = {
  providers: [
    {
      provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP,
      useValue: {
        "http://internal-host.internal": "https://mycoolapi.com",
      },
    },
  ],
};

We basically map ours server available host to client’s available domain and that’s it.

⚠️ Remember to provide it only in your app server config, when there will be provider on client, Angular will throw an error.

❗ Common mistake

A lot of times our public and internal endpoint fragments aren’t same. We can have some another prefix in our domains, or we’re using gateway service.

For example:
On the backend you can have http://internal-host.internal/api/endpoint and as public endpoint https://mycoolapi.com/gateway/endpoint

As you see there’s a mismatch in fragment - /api/endpoint !== /gateway/endpoint. Unfortunately, it will cause another call to API since fragment after mapped domains must be identical and in this case cache won’t work. Maybe in the future we will be able to solve this problem. There’s open issue on Github that points out this problem - https://github.com/angular/angular/issues/57080.

Conclusion

By implementing the HTTP_TRANSFER_CACHE_ORIGIN_MAP, you can maintain smooth hydration despite different server and client endpoints. This solution ensures your Angular SSR application remains fast, efficient, and flicker-free. 🚀

Sources


Me - Adam Weber