RenderContext
RenderContext is a core class in the Esmx framework, responsible for managing the full lifecycle of server-side rendering (SSR). It provides a complete API to handle rendering context, resource management, state synchronization, and more:
- Rendering control: manages SSR flows, supports multi-entry and conditional rendering
- Resource management: intelligently collects and injects static resources like JS and CSS to optimize load performance
- State synchronization: serializes server-side state to ensure correct client hydration
- Routing control: supports server-side redirects and status code settings
Type Definitions
ServerRenderHandle
Type definition for a server-side rendering handler.
type ServerRenderHandle = (rc: RenderContext) => Promise<void>;
The server rendering handler is an async or sync function that receives a RenderContext instance to perform SSR logic.
entry.node.ts
export default async (rc: RenderContext) => {
const app = createApp();
const html = await renderToString(app);
rc.html = html;
};
export const simple = async (rc: RenderContext) => {
rc.html = '<h1>Hello World</h1>';
};
RenderFiles
Type definition for the list of resource files collected during rendering.
interface RenderFiles {
js: string[];
css: string[];
modulepreload: string[];
resources: string[];
}
- js: JavaScript file list
- css: stylesheet file list
- modulepreload: ESM modules to preload
- resources: other asset files (images, fonts, etc.)
rc.files = {
js: [
'/assets/entry-client.js',
'/assets/vendor.js'
],
css: [
'/assets/main.css',
'/assets/vendor.css'
],
modulepreload: [
'/assets/Home.js',
'/assets/About.js'
],
resources: [
'/assets/logo.png',
'/assets/font.woff2'
]
};
ImportmapMode
Defines the generation mode of the import map.
type ImportmapMode = 'inline' | 'js';
inline: inline the import map directly into HTML, suitable when:
- reducing HTTP requests is desired
- the import map is small
- first-screen performance is critical
js: generate the import map as a separate JS file, suitable when:
- the import map is large
- leveraging browser cache is preferred
- multiple pages share the same import map
Rendering context class, responsible for resource management and HTML generation during SSR.
Instance Options
Defines configuration options for the rendering context.
interface RenderContextOptions {
base?: string
entryName?: string
params?: Record<string, any>
importmapMode?: ImportmapMode
}
base
Base path for static assets.
- all static resources (JS, CSS, images, etc.) load relative to this path
- supports runtime dynamic configuration without rebuilding
- commonly used in multilingual sites and micro-frontend applications
entryName
- Type:
string
- Default:
'default'
Server-side render entry function name. Used when a module exports multiple rendering functions.
src/entry.server.ts
export const mobile = async (rc: RenderContext) => {
};
export const desktop = async (rc: RenderContext) => {
};
params
- Type:
Record<string, any>
- Default:
{}
Rendering parameters. Arbitrary data can be passed to the rendering function, commonly request info such as URL and query.
const rc = await esmx.render({
params: {
url: req.url,
lang: 'zh-CN',
theme: 'dark'
}
});
importmapMode
- Type:
'inline' | 'js'
- Default:
'inline'
Import map generation mode:
inline: inline the import map into HTML
js: generate as a separate JS file
Instance Properties
esmx
- Type:
Esmx
- Readonly:
true
Reference to the Esmx instance. Provides access to core framework features and configuration.
redirect
- Type:
string | null
- Default:
null
Redirect location. When set, the server can perform an HTTP redirect. Common in login checks and access control.
entry.node.ts
export default async (rc: RenderContext) => {
if (!isLoggedIn()) {
rc.redirect = '/login';
rc.status = 302;
return;
}
};
export default async (rc: RenderContext) => {
if (!hasPermission()) {
rc.redirect = '/403';
rc.status = 403;
return;
}
};
status
- Type:
number | null
- Default:
null
HTTP response status code. Set any valid HTTP status code, commonly for errors and redirects.
entry.node.ts
export default async (rc: RenderContext) => {
const page = await findPage(rc.params.url);
if (!page) {
rc.status = 404;
return;
}
};
export default async (rc: RenderContext) => {
if (needMaintenance()) {
rc.redirect = '/maintenance';
rc.status = 307;
return;
}
};
html
HTML content. Sets and retrieves the final generated HTML. When setting, the base path placeholder is handled automatically.
entry.node.ts
export default async (rc: RenderContext) => {
rc.html = `
<!DOCTYPE html>
<html>
<head>
${rc.preload()}
${rc.css()}
</head>
<body>
<div id="app">Hello World</div>
${rc.importmap()}
${rc.moduleEntry()}
${rc.modulePreload()}
</body>
</html>
`;
};
const rc = await esmx.render({
base: '/app',
params: { url: req.url }
});
base
- Type:
string
- Readonly:
true
- Default:
''
Base path for static assets. All static resources (JS, CSS, images, etc.) load based on this path and can be configured at runtime.
const rc = await esmx.render({
base: '/esmx',
params: { url: req.url }
});
const rc = await esmx.render({
base: '/cn',
params: { lang: 'zh-CN' }
});
const rc = await esmx.render({
base: '/app1',
params: { appId: 1 }
});
entryName
- Type:
string
- Readonly:
true
- Default:
'default'
Server-side render entry function name. Selects which function in entry.server.ts to use.
entry.node.ts
export default async (rc: RenderContext) => {
};
export const mobile = async (rc: RenderContext) => {
};
export const desktop = async (rc: RenderContext) => {
};
const rc = await esmx.render({
entryName: isMobile ? 'mobile' : 'desktop',
params: { url: req.url }
});
params
- Type:
Record<string, any>
- Readonly:
true
- Default:
{}
Rendering parameters. Can be passed and accessed during SSR, commonly request info and page configuration.
const rc = await esmx.render({
params: {
url: req.url,
lang: 'zh-CN'
}
});
const rc = await esmx.render({
params: {
theme: 'dark',
layout: 'sidebar'
}
});
const rc = await esmx.render({
params: {
apiBaseUrl: process.env.API_BASE_URL,
version: '1.0.0'
}
});
Module dependency collection set. Automatically tracks and records module dependencies during component rendering, collecting only resources actually used for the current page render.
const renderToString = (app: any, context: { importMetaSet: Set<ImportMeta> }) => {
return '<div id="app">Hello World</div>';
};
const app = createApp();
const html = await renderToString(app, {
importMetaSet: rc.importMetaSet
});
files
Resource file list:
- js: JavaScript files
- css: stylesheet files
- modulepreload: ESM modules to preload
- resources: other resources
await rc.commit();
rc.html = `
<!DOCTYPE html>
<html>
<head>
${rc.preload()}
${rc.css()}
</head>
<body>
${html}
${rc.importmap()}
${rc.moduleEntry()}
${rc.modulePreload()}
</body>
</html>
`;
importmapMode
- Type:
'inline' | 'js'
- Default:
'inline'
Import map generation mode:
inline: inline the import map into HTML
js: generate as a JS file
Instance Methods
serialize()
- Parameters:
input: any
options?: serialize.SerializeJSOptions
- Returns:
string
Serializes a JavaScript object to a string. Used to safely embed state data into HTML during SSR.
const state = {
user: { id: 1, name: 'Alice' },
timestamp: new Date()
};
rc.html = `
<script>
window.__INITIAL_STATE__ = ${rc.serialize(state)};
</script>
`;
state()
- Parameters:
varName: string
data: Record<string, any>
- Returns:
string
Serializes and injects state data into HTML using a safe serialization method.
const userInfo = {
id: 1,
name: 'John',
roles: ['admin']
};
rc.html = `
<head>
${rc.state('__USER__', userInfo)}
</head>
`;
commit()
Commits dependency collection and updates the resource lists. Collects all used modules from importMetaSet and resolves concrete resources via the manifest.
const html = await renderToString(app, {
importMetaSet: rc.importMetaSet
});
await rc.commit();
preload()
Generates resource preload tags for CSS and JavaScript with priority support and base path handling.
rc.html = `
<!DOCTYPE html>
<html>
<head>
${rc.preload()}
${rc.css()}
</head>
<body>
${html}
${rc.importmap()}
${rc.moduleEntry()}
${rc.modulePreload()}
</body>
</html>
`;
css()
Generates CSS link tags, injecting collected stylesheets in the correct order.
rc.html = `
<head>
${rc.css()}
</head>
`;
importmap()
Generates the import map tag as configured by importmapMode (inline or external).
rc.html = `
<head>
${rc.importmap()}
</head>
`;
moduleEntry()
Generates the client entry module tag. Must be injected after the import map.
rc.html = `
<body>
${html}
${rc.importmap()}
${rc.moduleEntry()}
</body>
`;
modulePreload()
Generates module preload tags to optimize first-screen load.
rc.html = `
<body>
${html}
${rc.importmap()}
${rc.moduleEntry()}
${rc.modulePreload()}
</body>
`;