Esmx

Introduction

Esmx is a high-performance web application framework based on Rspack, providing comprehensive application lifecycle management, static asset handling, and server-side rendering capabilities.

Type Definitions

BuildSsrTarget

  • Type Definition:
1type BuildSsrTarget = 'client' | 'server'

Application runtime environment types:

  • client: Runs in browser environment, supports DOM operations and browser APIs
  • server: Runs in Node.js environment, supports filesystem and server-side functionalities

ImportMap

  • Type Definition:
1type ImportMap = {
2  imports?: SpecifierMap
3  scopes?: ScopesMap
4}

ES Module import map type.

SpecifierMap

  • Type Definition:
1type SpecifierMap = Record<string, string>

Module specifier mapping type, used to define module import path mappings.

ScopesMap

  • Type Definition:
1type ScopesMap = Record<string, SpecifierMap>

Scope mapping type, used to define module import mappings within specific scopes.

COMMAND

  • Type Definition:
1enum COMMAND {
2    dev = 'dev',
3    build = 'build',
4    preview = 'preview',
5    start = 'start'
6}

Command type enumeration:

  • dev: Development environment command, starts development server with hot reload
  • build: Build command, generates production build artifacts
  • preview: Preview command, launches local preview server
  • start: Start command, runs production server

Instance Options

Defines core configuration options for the Esmx framework.

1interface EsmxOptions {
2  root?: string
3  isProd?: boolean
4  basePathPlaceholder?: string | false
5  modules?: ModuleConfig
6  packs?: PackConfig
7  devApp?: (esmx: Esmx) => Promise<App>
8  server?: (esmx: Esmx) => Promise<void>
9  postBuild?: (esmx: Esmx) => Promise<void>
10}

root

  • Type: string
  • Default: process.cwd()

Project root directory path. Can be absolute or relative path (resolved relative to current working directory).

isProd

  • Type: boolean
  • Default: process.env.NODE_ENV === 'production'

Environment flag:

  • true: Production environment
  • false: Development environment

basePathPlaceholder

  • Type: string | false
  • Default: '[[[___GEZ_DYNAMIC_BASE___]]]'

Base path placeholder configuration. Used for runtime dynamic replacement of asset base paths. Set to false to disable this feature.

modules

  • Type: ModuleConfig

Module configuration options. Used to configure project module resolution rules, including module aliases, external dependencies, etc.

packs

  • Type: PackConfig

Packaging configuration options. Used to package build artifacts into standard npm .tgz format packages.

devApp

  • Type: (esmx: Esmx) => Promise<App>

Development environment application creation function. Only used in development environment to create application instances for development server.

entry.node.ts
1export default {
2  async devApp(esmx) {
3    return import('@esmx/rspack').then((m) =>
4      m.createRspackHtmlApp(esmx, {
5        config(context) {
6          // Custom Rspack configuration
7        }
8      })
9    )
10  }
11}

server

  • Type: (esmx: Esmx) => Promise<void>

Server startup configuration function. Used to configure and start HTTP server, available in both development and production environments.

entry.node.ts
1export default {
2  async server(esmx) {
3    const server = http.createServer((req, res) => {
4      esmx.middleware(req, res, async () => {
5        const render = await esmx.render({
6          params: { url: req.url }
7        });
8        res.end(render.html);
9      });
10    });
11
12    server.listen(3000);
13  }
14}

postBuild

  • Type: (esmx: Esmx) => Promise<void>

Post-build processing function. Executed after project build completes, can be used for:

  • Additional resource processing
  • Deployment operations
  • Generating static files
  • Sending build notifications

Instance Properties

name

  • Type: string
  • Read-only: true

Current module name, derived from module configuration.

varName

  • Type: string
  • Read-only: true

Valid JavaScript variable name generated from module name.

root

  • Type: string
  • Read-only: true

Absolute path to project root directory. If configured root is relative path, resolved relative to current working directory.

isProd

  • Type: boolean
  • Read-only: true

Determines whether current environment is production. Prioritizes isProd from configuration, otherwise uses process.env.NODE_ENV.

basePath

  • Type: string
  • Read-only: true
  • Throws: NotReadyError - When framework is not initialized

Gets module base path with leading and trailing slashes. Returns format /${name}/, where name comes from module configuration.

basePathPlaceholder

  • Type: string
  • Read-only: true

Gets base path placeholder for runtime dynamic replacement. Can be disabled via configuration.

middleware

  • Type: Middleware
  • Read-only: true

Gets static asset handling middleware. Provides different implementations based on environment:

  • Development: Supports real-time compilation and hot reload
  • Production: Supports long-term caching of static assets
1const server = http.createServer((req, res) => {
2  esmx.middleware(req, res, async () => {
3    const rc = await esmx.render({ url: req.url });
4    res.end(rc.html);
5  });
6});

render

  • Type: (options?: RenderContextOptions) => Promise<RenderContext>
  • Read-only: true

Gets server-side rendering function. Provides different implementations based on environment:

  • Development: Supports hot reload and real-time preview
  • Production: Provides optimized rendering performance
1// Basic usage
2const rc = await esmx.render({
3  params: { url: req.url }
4});
5
6// Advanced configuration
7const rc = await esmx.render({
8  base: '',                    // Base path
9  importmapMode: 'inline',     // Import map mode
10  entryName: 'default',        // Rendering entry
11  params: {
12    url: req.url,
13    state: { user: 'admin' }   // State data
14  }
15});

COMMAND

  • Type: typeof COMMAND
  • Read-only: true

Gets command enumeration type definition.

moduleConfig

  • Type: ParsedModuleConfig
  • Read-only: true
  • Throws: NotReadyError - When framework is not initialized

Gets complete configuration information for current module, including module resolution rules, alias configurations, etc.

packConfig

  • Type: ParsedPackConfig
  • Read-only: true
  • Throws: NotReadyError - When framework is not initialized

Gets packaging-related configuration for current module, including output paths, package.json processing, etc.

Instance Methods

constructor()

  • Parameters:
    • options?: EsmxOptions - Framework configuration options
  • Returns: Esmx

Creates Esmx framework instance.

1const esmx = new Esmx({
2  root: './src',
3  isProd: process.env.NODE_ENV === 'production'
4});

init()

  • Parameters: command: COMMAND
  • Returns: Promise<boolean>
  • Throws:
    • Error: When initializing repeatedly
    • NotReadyError: When accessing uninitialized instance

Initializes Esmx framework instance. Executes core initialization processes:

  1. Resolves project configuration (package.json, module config, pack config, etc.)
  2. Creates application instance (development or production environment)
  3. Executes corresponding lifecycle methods based on command
Note
  • Throws error when initializing repeatedly
  • Throws NotReadyError when accessing uninitialized instance :::
1const esmx = new Esmx({
2  root: './src',
3  isProd: process.env.NODE_ENV === 'production'
4});
5
6await esmx.init(COMMAND.dev);

destroy()

  • Returns: Promise<boolean>

Destroys Esmx framework instance, performs resource cleanup and connection closing. Mainly used for:

  • Shutting down development server
  • Cleaning temporary files and caches
  • Releasing system resources
1process.once('SIGTERM', async () => {
2  await esmx.destroy();
3  process.exit(0);
4});

build()

  • Returns: Promise<boolean>

Executes application build process, including:

  • Compiling source code
  • Generating production build artifacts
  • Optimizing and minifying code
  • Generating asset manifests

::: warning Note Throws NotReadyError when called on uninitialized framework instance

entry.node.ts
1export default {
2  async postBuild(esmx) {
3    await esmx.build();
4    // Generate static HTML after build
5    const render = await esmx.render({
6      params: { url: '/' }
7    });
8    esmx.writeSync(
9      esmx.resolvePath('dist/client', 'index.html'),
10      render.html
11    );
12  }
13}

server()

  • Returns: Promise<void>
  • Throws: NotReadyError - When framework is not initialized

Starts HTTP server and configures server instance. Called during following lifecycles:

  • Development (dev): Starts development server with hot reload
  • Production (start): Starts production server with production-grade performance
entry.node.ts
1export default {
2  async server(esmx) {
3    const server = http.createServer((req, res) => {
4      // Handle static assets
5      esmx.middleware(req, res, async () => {
6        // Server-side rendering
7        const render = await esmx.render({
8          params: { url: req.url }
9        });
10        res.end(render.html);
11      });
12    });
13
14    server.listen(3000, () => {
15      console.log('Server running at http://localhost:3000');
16    });
17  }
18}

postBuild()

  • Returns: Promise<boolean>

Executes post-build processing logic, used for:

  • Generating static HTML files
  • Processing build artifacts
  • Executing deployment tasks
  • Sending build notifications
entry.node.ts
1export default {
2  async postBuild(esmx) {
3    // Generate static HTML for multiple pages
4    const pages = ['/', '/about', '/404'];
5
6    for (const url of pages) {
7      const render = await esmx.render({
8        params: { url }
9      });
10
11      await esmx.write(
12        esmx.resolvePath('dist/client', url.substring(1), 'index.html'),
13        render.html
14      );
15    }
16  }
17}

resolvePath

Resolves project path, converts relative paths to absolute paths.

  • Parameters:

    • projectPath: ProjectPath - Project path type
    • ...args: string[] - Path segments
  • Returns: string - Resolved absolute path

  • Example:

1// Resolve static asset path
2const htmlPath = esmx.resolvePath('dist/client', 'index.html');

writeSync()

Synchronously writes file content.

  • Parameters:

    • filepath: string - Absolute file path
    • data: any - Data to write, can be string, Buffer or object
  • Returns: boolean - Whether write succeeded

  • Example:

src/entry.node.ts
1async postBuild(esmx) {
2  const htmlPath = esmx.resolvePath('dist/client', 'index.html');
3  const success = await esmx.write(htmlPath, '<html>...</html>');
4}

readJsonSync()

Synchronously reads and parses JSON file.

  • Parameters:

    • filename: string - Absolute path to JSON file
  • Returns: any - Parsed JSON object

  • Exceptions: Throws when file doesn't exist or JSON is malformed

  • Example:

src/entry.node.ts
1async server(esmx) {
2  const manifest = esmx.readJsonSync(esmx.resolvePath('dist/client', 'manifest.json'));
3  // Use manifest object
4}

readJson()

Asynchronously reads and parses JSON file.

  • Parameters:

    • filename: string - Absolute path to JSON file
  • Returns: Promise<any> - Parsed JSON object

  • Exceptions: Throws when file doesn't exist or JSON is malformed

  • Example:

src/entry.node.ts
1async server(esmx) {
2  const manifest = await esmx.readJson(esmx.resolvePath('dist/client', 'manifest.json'));
3  // Use manifest object
4}

getManifestList()

Gets build manifest list.

  • Parameters:

    • target: BuildSsrTarget - Target environment type
      • 'client': Client environment
      • 'server': Server environment
  • Returns: Promise<readonly ManifestJson[]> - Read-only build manifest list

  • Exceptions: Throws NotReadyError when framework instance is not initialized

This method retrieves build manifest list for specified target environment, with following features:

  1. Cache Management

    • Uses internal caching mechanism to avoid repeated loading
    • Returns immutable manifest list
  2. Environment Adaptation

    • Supports both client and server environments
    • Returns corresponding manifest information based on target environment
  3. Module Mapping

    • Contains module export information
    • Records asset dependencies
  • Example:
src/entry.node.ts
1async server(esmx) {
2  // Get client build manifest
3  const manifests = await esmx.getManifestList('client');
4
5  // Find build information for specific module
6  const appModule = manifests.find(m => m.name === 'my-app');
7  if (appModule) {
8    console.log('App exports:', appModule.exports);
9    console.log('App chunks:', appModule.chunks);
10  }
11}

getImportMap()

Gets import map object.

  • Parameters:

    • target: BuildSsrTarget - Target environment type
      • 'client': Generates browser environment import map
      • 'server': Generates server environment import map
  • Returns: Promise<Readonly<ImportMap>> - Read-only import map object

  • Exceptions: Throws NotReadyError when framework instance is not initialized

This method generates ES Module import maps (Import Map), with following characteristics:

  1. Module Resolution

    • Generates module mappings based on build manifest
    • Supports both client and server environments
    • Automatically handles module path resolution
  2. Cache Optimization

    • Uses internal caching mechanism
    • Returns immutable mapping object
  3. Path Handling

    • Automatically processes module paths
    • Supports dynamic base paths
  • Example:
src/entry.node.ts
1async server(esmx) {
2  // Get client import map
3  const importmap = await esmx.getImportMap('client');
4
5  // Custom HTML template
6  const html = `
7    <!DOCTYPE html>
8    <html>
9    <head>
10      <script type="importmap">
11        ${JSON.stringify(importmap)}
12      </script>
13    </head>
14    <body>
15      <!-- Page content -->
16    </body>
17    </html>
18  `;
19}

getImportMapClientInfo()

Gets client import map information.

  • Parameters:

    • mode: ImportmapMode - Import map mode
      • 'inline': Inline mode, returns HTML script tag
      • 'js': JS file mode, returns information with file path
  • Returns:

    • JS file mode:
      1{
      2  src: string;      // JS file URL
      3  filepath: string;  // JS file local path
      4  code: string;      // HTML script tag content
      5}
    • Inline mode:
      1{
      2  src: null;
      3  filepath: null;
      4  code: string;      // HTML script tag content
      5}
  • Exceptions: Throws NotReadyError when framework instance is not initialized

This method generates client environment import map code, supporting two modes:

  1. Inline Mode (inline)

    • Inlines import map directly into HTML
    • Reduces additional network requests
    • Suitable for smaller import maps
  2. JS File Mode (js)

    • Generates standalone JS file
    • Supports browser caching
    • Suitable for larger import maps

Core features:

  • Automatically handles dynamic base paths

  • Supports runtime module path replacement

  • Optimizes caching strategy

  • Ensures module loading order

  • Example:

src/entry.node.ts
1async server(esmx) {
2  const server = express();
3  server.use(esmx.middleware);
4
5  server.get('*', async (req, res) => {
6    // Use JS file mode
7    const result = await esmx.render({
8      importmapMode: 'js',
9      params: { url: req.url }
10    });
11    res.send(result.html);
12  });
13
14  // Or use inline mode
15  server.get('/inline', async (req, res) => {
16    const result = await esmx.render({
17      importmapMode: 'inline',
18      params: { url: req.url }
19    });
20    res.send(result.html);
21  });
22}

getStaticImportPaths()

Gets module's static import path list.

  • Parameters:

    • target: BuildSsrTarget - Build target
      • 'client': Client environment
      • 'server': Server environment
    • specifier: string - Module specifier
  • Returns: Promise<readonly string[] | null> - Returns static import path list, returns null if not found

  • Exceptions: Throws NotReadyError when framework instance is not initialized

  • Example:

1// Get static import paths for client entry module
2const paths = await esmx.getStaticImportPaths(
3  'client',
4  `your-app-name/src/entry.client`
5);