Webpack SSR
Webpack SSR
This page describes sku’s older method for server-side rendering using Webpack. For the new experimental Managed Data Mode SSR, see Getting started.
Webpack SSR uses a low-level API and custom -ssr commands (sku start-ssr / sku build-ssr). You supply a serverEntry whose default export includes renderCallback.
Minimal setup
import type { SkuConfig } from 'sku';
export default {
clientEntry: 'src/client.tsx',
serverEntry: 'src/server/server.tsx',
public: 'src/public',
publicPath: '/',
target: 'dist',
port: 3300,
serverPort: 3301,
} satisfies SkuConfig;sku provides an Express server. The serverEntry default export may provide renderCallback, optional middleware, and optional onStart. sku calls onStart once after listen succeeds. The first argument is the Express app. The second argument carries httpServer and the bound port. Use httpServer for keep-alive timeouts and to close the server on SIGTERM.
import type { Server } from 'sku';
import middleware from './middleware';
import template from './template';
export default (): Server => ({
renderCallback: ({ SkuProvider, getBodyTags, getHeadTags }, req, res) => {
const app = renderToString(
<SkuProvider>
<App />
</SkuProvider>,
);
res.send(
template({ headTags: getHeadTags(), bodyTags: getBodyTags(), app }),
);
},
middleware,
onStart: (app, { httpServer, port }) => {
httpServer.keepAliveTimeout = 20_000;
console.log('My app started on port', port);
process.on('SIGTERM', () => {
httpServer.close(() => {
process.exit(0);
});
});
},
});Commands
These differ from Managed Data Mode SSR and Static apps:
sku start-ssr— development. Uses bothportandserverPortsku build-ssr— production assets. Run withnode ./dist/server.js(listens onserverPort)sku test— tests
Multi-part response
To return HTML at different times in the request, use flushHeadTags for head tags added since the previous call (typically from dynamic chunks):
import type { Server } from 'sku';
import { followupResponseTemplate, initialResponseTemplate } from './template';
import middleware from './middleware';
export default (): Server => ({
renderCallback: async (
{ SkuProvider, getBodyTags, flushHeadTags },
req,
res,
) => {
res.status(200);
// Call `flushHeadTags` early to retrieve whatever tags are available.
res.write(initialResponseTemplate({ headTags: flushHeadTags() }));
await Promise.resolve();
const app = renderToString(
<SkuProvider>
<App />
</SkuProvider>,
);
res.write(
// Call `flushHeadTags` again just in case new tags are available.
followupResponseTemplate({
headTags: flushHeadTags(),
bodyTags: getBodyTags(),
app,
}),
);
res.end();
},
middleware,
onStart: (app, { httpServer, port }) => {
httpServer.keepAliveTimeout = 20_000;
console.log('My app started on port', port);
process.on('SIGTERM', () => {
httpServer.close(() => {
process.exit(0);
});
});
},
});Multi-language support
When you use multiple languages, the browser downloads the language as needed. That download can delay first paint. To ensure translations are available immediately, call addLanguageChunk from your render params:
export async function serverRender({ SkuProvider, addLanguageChunk, appPath }) {
const language = getLanguageFromPath(appPath);
addLanguageChunk(language);
return renderToString(
<SkuProvider>
<StaticRouter location={appPath}>
<VocabProvider language={language}>
<App />
</VocabProvider>
</StaticRouter>
</SkuProvider>,
);
}Static rendering registers language chunks automatically. Managed Data Mode SSR uses server-entry getLanguage instead. See Multi-language.
Development server entrypoint
On the Webpack SSR path, sku start-ssr starts two services:
- A dev server for static assets
- An SSR service running your app’s server code
The dev server is the single entrypoint. It proxies non-asset requests to the SSR service. That pattern is similar to a production reverse proxy. It also avoids CORS for client requests. Managed Data Mode SSR uses a single port instead.
To proxy other traffic (for example APIs), use Dev Server Middleware.
See also
- Migrate from Webpack SSR — move to Managed Data Mode
- Getting started — Managed Data Mode overview
- Extra features —
devServerMiddleware
