Skip to content

SSR and hydration

Prerendering, adoption of server DOM, and caching.

Blasdoc runs where there is no browser, and it can adopt the DOM a server produced instead of rebuilding it.

Prerendering

@blasdoc/core never touches a browser global on the parse path, the renderer builds DOM through Renderer2, and the theme injects DOCUMENT rather than reaching for it. So Angular's prerender walks a Blasdoc site without knowing anything about Markdown:

ts
// app.config.server.ts
export const serverConfig: ApplicationConfig = {
  providers: [provideServerRendering()],
};
json
{
  "outputMode": "static",
  "prerender": true
}

This site is built that way: every page you read arrived as HTML, with its metadata already in the head.

Hydration by adoption

ts
providers: [
  provideClientHydration(),
  provideBlasdoc(),
  provideBlasdocHydration(),
];

With that last provider the client walks the server's DOM alongside the IR, keeping every node that matches and replacing the rest. It is recursive, so nested content is kept too. That removes the rebuild and the flash.

Caching

Parsing is deterministic, so it is worth doing once:

ts
import { BlasdocParserCache, createBlasdocParser } from '@blasdoc/core';
 
const cache = new BlasdocParserCache(createBlasdocParser());
cache.parse(markdown); // parsed once, reused after

Expressions and highlighted blocks are cached too — the highlight cache holds 200 entries, keyed by theme, language, meta and code.

The caches are in-memory and per-instance: nothing is shared across requests or persisted. That is deliberate, and it is the honest description.

What SSR does not do

There is no streaming, no partial hydration and no island model. A page renders on the server, arrives as HTML, and the client adopts it.