Skip to main content

Server-side Rendering

Prerequisites​

An Angular project with server-side rendering enabled.

Overview​

Orbit supports server-side rendering in two ways:

  1. It uses Angular's HttpClient under the hood which automatically supports server-side rendering as explained here.
  2. It uses Angular's TransferState to transfer Apollo Client's cache from server to client.

signal.query and signal.query.once use PendingTasks so SSR waits for execution, variable changes, refetch and fetchMore. Termination releases pending tasks. Polling after the first execution, mutations and subscriptions do not hold application stability.

With custom scalars, cache.extract() serializes values for transfer and cache.restore() parses them again. Configure the same scalars on the server and browser caches.

Setup​

Setup SSR based on your angular project's style.

Update appConfig​

app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideGraphQL } from './graphql/graphql.provider';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { provideClientHydration, withHttpTransferCacheOptions } from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideGraphQL(),
provideHttpClient(withFetch()),
provideClientHydration(withHttpTransferCacheOptions({
includePostRequests: true
}))
]
};

Passing includePostRequests to withHttpTransferCacheOptions is required for default GraphQL setup where POST requests are used.

Update provideGraphQL​

app/graphql/graphql.provider.ts
import { isPlatformBrowser } from '@angular/common';
import { EnvironmentProviders, PLATFORM_ID, TransferState, inject, makeEnvironmentProviders, makeStateKey, provideEnvironmentInitializer } from '@angular/core';
import { Apollo, InMemoryCache, provideApollo, withApolloOptions } from '@apollo-orbit/angular';
import { HttpLinkFactory, withHttpLink } from '@apollo-orbit/angular/http';
import { NormalizedCacheObject } from '@apollo/client';

const APOLLO_STATE_KEY = makeStateKey<NormalizedCacheObject>('APOLLO_STATE');

export function provideGraphQL(): EnvironmentProviders {
return makeEnvironmentProviders([
provideApollo(
withApolloOptions(() => {
const httpLinkFactory = inject(HttpLinkFactory);
const httpLink = httpLinkFactory.create({ uri: 'http://localhost:4000/graphql' });
const platformId = inject<object>(PLATFORM_ID);

const ssrOptions = isPlatformBrowser(platformId)
? { ssrForceFetchDelay: 200 }
: { ssrMode: true };

return {
link: httpLink,
cache: new InMemoryCache(),
...ssrOptions
};
}),
withHttpLink()
),
provideEnvironmentInitializer(() => {
const apollo = inject(Apollo);
const transferState = inject(TransferState);
const platformId = inject(PLATFORM_ID);

if (isPlatformBrowser(platformId)) {
const state = transferState.get(APOLLO_STATE_KEY, undefined);
if (state) apollo.cache.restore(state);
} else {
transferState.onSerialize(APOLLO_STATE_KEY, () => apollo.cache.extract());
}
})
]);
}