RenderContext

RenderContext is the core class in the Esmx framework, responsible for managing the complete lifecycle of server-side rendering (SSR). It provides a comprehensive API for handling rendering context, resource management, state synchronization, and other critical tasks:

  • Rendering Control: Manages server-side rendering workflows, supporting multi-entry rendering, conditional rendering, and other scenarios
  • Resource Management: Intelligently collects and injects static resources like JS and CSS to optimize loading performance
  • State Synchronization: Handles server-side state serialization to ensure proper client-side hydration
  • Routing Control: Supports advanced features like server-side redirects and status code configuration

Type Definitions

ServerRenderHandle

Type definition for server-side rendering handler functions.

1type ServerRenderHandle = (rc: RenderContext) => Promise<void> | void;

A server-side rendering handler is an async or sync function that receives a RenderContext instance as parameter for processing SSR logic.

entry.node.ts
1// 1. Async handler
2export default async (rc: RenderContext) => {
3  const app = createApp();
4  const html = await renderToString(app);
5  rc.html = html;
6};
7
8// 2. Sync handler
9export const simple = (rc: RenderContext) => {
10  rc.html = '<h1>Hello World</h1>';
11};

RenderFiles

Type definition for resource file lists collected during rendering.

1interface RenderFiles {
2  js: string[];
3  css: string[];
4  modulepreload: string[];
5  resources: string[];
6}
  • js: JavaScript file list
  • css: Stylesheet file list
  • modulepreload: List of ESM modules requiring preloading
  • resources: Other resource file list (images, fonts, etc.)
1// Example resource file list
2rc.files = {
3  js: [
4    '/assets/entry-client.js',
5    '/assets/vendor.js'
6  ],
7  css: [
8    '/assets/main.css',
9    '/assets/vendor.css'
10  ],
11  modulepreload: [
12    '/assets/Home.js',
13    '/assets/About.js'
14  ],
15  resources: [
16    '/assets/logo.png',
17    '/assets/font.woff2'
18  ]
19};

ImportmapMode

Defines importmap generation modes.

1type ImportmapMode = 'inline' | 'js';
  • inline: Inlines importmap content directly into HTML, suitable for:
    • Reducing HTTP requests
    • Smaller importmap content
    • Critical first-load performance requirements
  • js: Generates importmap as standalone JS file, suitable for:
    • Larger importmap content
    • Leveraging browser caching
    • Shared importmaps across multiple pages

The rendering context class responsible for resource management and HTML generation during server-side rendering (SSR).

Instance Options

Configuration options for RenderContext.

1interface RenderContextOptions {
2  base?: string
3  entryName?: string
4  params?: Record<string, any>
5  importmapMode?: ImportmapMode
6}

base

  • Type: string
  • Default: ''

Base path for static resources.

  • All static resources (JS, CSS, images, etc.) will load relative to this path
  • Supports runtime dynamic configuration without rebuild
  • Commonly used for multilingual sites, micro-frontend applications, etc.

entryName

  • Type: string
  • Default: 'default'

Server-side rendering entry function name. Specifies which entry function to use when a module exports multiple render functions.

src/entry.server.ts
1export const mobile = async (rc: RenderContext) => {
2  // Mobile rendering logic
3};
4
5export const desktop = async (rc: RenderContext) => {
6  // Desktop rendering logic
7};

params

  • Type: Record<string, any>
  • Default: {}

Rendering parameters. Can pass arbitrary parameters to render functions, commonly used for request information (URL, query params, etc.).

1const rc = await esmx.render({
2  params: {
3    url: req.url,
4    lang: 'zh-CN',
5    theme: 'dark'
6  }
7});

importmapMode

  • Type: 'inline' | 'js'
  • Default: 'inline'

Import Map generation mode:

  • inline: Inlines importmap content directly into HTML

  • js: Generates importmap as standalone JS file

Instance Properties

esmx

  • Type: Esmx
  • Readonly: true

Reference to the Esmx instance. Used to access core framework functionality and configuration.

redirect

  • Type: string | null
  • Default: null

Redirect URL. When set, the server can perform HTTP redirects based on this value, commonly used for login verification, permission control, etc.

entry.node.ts
1// Login verification example
2export default async (rc: RenderContext) => {
3  if (!isLoggedIn()) {
4    rc.redirect = '/login';
5    rc.status = 302;
6    return;
7  }
8  // Continue rendering...
9};
10
11// Permission control example
12export default async (rc: RenderContext) => {
13  if (!hasPermission()) {
14    rc.redirect = '/403';
15    rc.status = 403;
16    return;
17  }
18  // Continue rendering...
19};

status

  • Type: number | null
  • Default: null

HTTP response status code. Can set any valid HTTP status code, commonly used for error handling, redirects, etc.

entry.node.ts
1// 404 error handling example
2export default async (rc: RenderContext) => {
3  const page = await findPage(rc.params.url);
4  if (!page) {
5    rc.status = 404;
6    // Render 404 page...
7    return;
8  }
9  // Continue rendering...
10};
11
12// Temporary redirect example
13export default async (rc: RenderContext) => {
14  if (needMaintenance()) {
15    rc.redirect = '/maintenance';
16    rc.status = 307; // Temporary redirect preserving request method
17    return;
18  }
19  // Continue rendering...
20};

html

  • Type: string
  • Default: ''

HTML content. Used to set and get final generated HTML content, automatically processes base path placeholders when setting.

entry.node.ts
1// Basic usage
2export default async (rc: RenderContext) => {
3  // Set HTML content
4  rc.html = `
5    <!DOCTYPE html>
6    <html>
7      <head>
8        ${rc.preload()}
9        ${rc.css()}
10      </head>
11      <body>
12        <div id="app">Hello World</div>
13        ${rc.importmap()}
14        ${rc.moduleEntry()}
15        ${rc.modulePreload()}
16      </body>
17    </html>
18  `;
19};
20
21// Dynamic base path
22const rc = await esmx.render({
23  base: '/app',  // Set base path
24  params: { url: req.url }
25});
26
27// Placeholders in HTML are automatically replaced:
28// [[[___GEZ_DYNAMIC_BASE___]]]/your-app-name/css/style.css
29// Becomes:
30// /app/your-app-name/css/style.css

base

  • Type: string
  • Readonly: true
  • Default: ''

Base path for static resources. All static resources (JS, CSS, images, etc.) load relative to this path, supports runtime dynamic configuration.

1// Basic usage
2const rc = await esmx.render({
3  base: '/esmx',  // Set base path
4  params: { url: req.url }
5});
6
7// Multilingual site example
8const rc = await esmx.render({
9  base: '/cn',  // Chinese site
10  params: { lang: 'zh-CN' }
11});
12
13// Micro-frontend example
14const rc = await esmx.render({
15  base: '/app1',  // Sub-application 1
16  params: { appId: 1 }
17});

entryName

  • Type: string
  • Readonly: true
  • Default: 'default'

Server-side rendering entry function name. Used to select which render function to use from entry.server.ts.

entry.node.ts
1// Default entry function
2export default async (rc: RenderContext) => {
3  // Default rendering logic
4};
5
6// Multiple entry functions
7export const mobile = async (rc: RenderContext) => {
8  // Mobile rendering logic
9};
10
11export const desktop = async (rc: RenderContext) => {
12  // Desktop rendering logic
13};
14
15// Select entry function by device type
16const rc = await esmx.render({
17  entryName: isMobile ? 'mobile' : 'desktop',
18  params: { url: req.url }
19});

params

  • Type: Record<string, any>
  • Readonly: true
  • Default: {}

Rendering parameters. Can pass and access parameters during SSR, commonly used for request information, page configuration, etc.

1// Basic usage - passing URL and language settings
2const rc = await esmx.render({
3  params: {
4    url: req.url,
5    lang: 'zh-CN'
6  }
7});
8
9// Page configuration - setting theme and layout
10const rc = await esmx.render({
11  params: {
12    theme: 'dark',
13    layout: 'sidebar'
14  }
15});
16
17// Environment configuration - injecting API address
18const rc = await esmx.render({
19  params: {
20    apiBaseUrl: process.env.API_BASE_URL,
21    version: '1.0.0'
22  }
23});

importMetaSet

  • Type: Set<ImportMeta>

Module dependency collection set. Automatically tracks and records module dependencies during component rendering, only collecting resources actually used during current page rendering.

1// Basic usage
2const renderToString = (app: any, context: { importMetaSet: Set<ImportMeta> }) => {
3  // Automatically collects module dependencies during rendering
4  // Framework automatically calls context.importMetaSet.add(import.meta) during component rendering
5  // Developers don't need to manually handle dependency collection
6  return '<div id="app">Hello World</div>';
7};
8
9// Usage example
10const app = createApp();
11const html = await renderToString(app, {
12  importMetaSet: rc.importMetaSet
13});

files

  • Type: RenderFiles

Resource file list:

  • js: JavaScript file list
  • css: Stylesheet file list
  • modulepreload: List of ESM modules requiring preloading
  • resources: Other resource file list (images, fonts, etc.)
1// Resource collection
2await rc.commit();
3
4// Resource injection
5rc.html = `
6  <!DOCTYPE html>
7  <html>
8  <head>
9    <!-- Preload resources -->
10    ${rc.preload()}
11    <!-- Inject stylesheets -->
12    ${rc.css()}
13  </head>
14  <body>
15    ${html}
16    ${rc.importmap()}
17    ${rc.moduleEntry()}
18    ${rc.modulePreload()}
19  </body>
20  </html>
21`;

importmapMode

  • Type: 'inline' | 'js'
  • Default: 'inline'

Import Map generation mode:

  • inline: Inlines importmap content directly into HTML

  • js: Generates importmap as standalone JS file

Instance Methods

serialize()

  • Parameters:
    • input: any - Data to serialize
    • options?: serialize.SerializeJSOptions - Serialization options
  • Returns: string

Serializes JavaScript objects to strings. Used during SSR to serialize state data for safe embedding in HTML.

1const state = {
2  user: { id: 1, name: 'Alice' },
3  timestamp: new Date()
4};
5
6rc.html = `
7  <script>
8    window.__INITIAL_STATE__ = ${rc.serialize(state)};
9  </script>
10`;

state()

  • Parameters:
    • varName: string - Variable name
    • data: Record<string, any> - State data
  • Returns: string

Serializes and injects state data into HTML. Uses safe serialization methods supporting complex data structures.

1const userInfo = {
2  id: 1,
3  name: 'John',
4  roles: ['admin']
5};
6
7rc.html = `
8  <head>
9    ${rc.state('__USER__', userInfo)}
10  </head>
11`;

commit()

  • Returns: Promise<void>

Commits dependency collection and updates resource list. Collects all used modules from importMetaSet, resolves each module's specific resources based on manifest file.

1// Render and commit dependencies
2const html = await renderToString(app, {
3  importMetaSet: rc.importMetaSet
4});
5
6// Commit dependency collection
7await rc.commit();

preload()

  • Returns: string

Generates resource preload tags. Preloads CSS and JavaScript resources with priority configuration, automatically handles base paths.

1rc.html = `
2  <!DOCTYPE html>
3  <html>
4  <head>
5    ${rc.preload()}
6    ${rc.css()}  <!-- Inject stylesheets -->
7  </head>
8  <body>
9    ${html}
10    ${rc.importmap()}
11    ${rc.moduleEntry()}
12    ${rc.modulePreload()}
13  </body>
14  </html>
15`;

css()

  • Returns: string

Generates CSS stylesheet tags. Injects collected CSS files ensuring proper loading order.

1rc.html = `
2  <head>
3    ${rc.css()}  <!-- Inject all collected stylesheets -->
4  </head>
5`;

importmap()

  • Returns: string

Generates import map tags. Generates inline or external import maps based on importmapMode configuration.

1rc.html = `
2  <head>
3    ${rc.importmap()}  <!-- Inject import map -->
4  </head>
5`;

moduleEntry()

  • Returns: string

Generates client entry module tags. Injects client entry module, must execute after importmap.

1rc.html = `
2  <body>
3    ${html}
4    ${rc.importmap()}
5    ${rc.moduleEntry()}  <!-- Inject client entry module -->
6  </body>
7`;

modulePreload()

  • Returns: string

Generates module preload tags. Preloads collected ESM modules to optimize first-load performance.

1rc.html = `
2  <body>
3    ${html}
4    ${rc.importmap()}
5    ${rc.moduleEntry()}
6    ${rc.modulePreload()}  <!-- Preload module dependencies -->
7  </body>
8`;