SSR Stream Interception
How to intercept SSR stream to inject content before it is sent to the client.
Additional Content Injection in SSR
In some cases you may want to inject additional content into the SSR stream before it's sent to the client. This can be useful for injecting properties onto the document's root element (e.g., the lang attribute or a class name based on the user's request headers).
Step 1: Create a custom middleware for Waku
Create a new file in your project, for example ./src/middleware/stream-interceptor.ts:
import type { Middleware } from 'waku/config';
// key below is probably best to have at a central config location to allow for it to be changed easily
export const themeCookieKey = 'waku-color-theme';
const streamInterceptor: Middleware = () => {
return async (ctx, next) => {
const theme = ctx.context.theme;
await next();
ctx.res.headers ||= {};
const isDocument = ctx.res.headers['content-type']?.includes('text/html');
const lang = 'en-US';
if (isDocument) {
const documentContent = ctx.res.body;
const newDocumentContent = documentContent?.pipeThrough(
new TransformStream({
async transform(chunk, controller) {
const text = new TextDecoder().decode(chunk);
const newText = text.replace(
'<html>',
`<html lang="${lang}" ${theme == 'dark' ? "class='dark'" : ''}>`,
);
controller.enqueue(new TextEncoder().encode(newText));
},
}),
);
ctx.res.body = newDocumentContent!;
}
};
};
export default streamInterceptor;
Step 2: Register the middleware
In your waku.config.ts file, import the middleware and add it to the middleware array:
import streamInterceptor from './src/middleware/stream-interceptor';
import { defineConfig } from 'waku/config';
export default defineConfig({
// ...
middleware: () => [
import('waku/middleware/context'),
import('./src/middleware/themePreload.js'), // + this is the one we just added
import('waku/middleware/dev-server'),
import('waku/middleware/handler'),
],
});
Step 3: Restart the server
After adding the middleware, you'll need to restart the server for the changes to take effect.
Step 4: Verify the changes
After restarting the server, you can verify that the changes have taken effect by inspecting the HTML source of your page. You should see the lang attribute and, if your system is set to dark mode, the class attribute on the <html> element as well.