For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /config/dev/lazy-compilation.md.
close

dev.lazyCompilation

  • Type:
type LazyCompilationOptions =
  | boolean
  | {
      /**
       * Enable lazy compilation for entries.
       */
      entries?: boolean;
      /**
       * Enable lazy compilation for dynamic imports.
       */
      imports?: boolean;
      /**
       * Specify which imported modules should be lazily compiled.
       */
      test?: RegExp | ((m: Module) => boolean);
      /**
       * The path to a custom runtime code that overrides the default lazy compilation client.
       */
      client?: string;
      /**
       * Tells the client the server URL that needs to be requested.
       */
      serverUrl?: string;
      /**
       * Customize the prefix used for lazy compilation endpoint.
       * @default "/lazy-compilation-using-"
       */
      prefix?: string;
      /**
       * Enable lazy compilation for Node targets.
       * The application must retain and update the emitted runtime.
       * @default false
       */
      node?: boolean;
    };
  • Default:
const defaultOptions = {
  imports: true,
  entries: false,
};

Enable lazy compilation (compilation on demand), implemented based on Rspack's lazy compilation feature.

Introduction

Although Rspack itself has good performance, the overall build time can still be less than ideal when building applications with a large number of modules. This is because the modules in the application need to be compiled by various loaders, such as postcss-loader, sass-loader, vue-loader, etc., which introduce additional compilation overhead.

Lazy compilation is an effective strategy to improve the startup performance of the development phase. Instead of compiling all modules at initialization, it compiles modules on demand as they are needed. This means that developers can quickly see the application running when starting the dev server, and build the required modules in batches. By compiling on demand, unnecessary compilation time can be reduced. As the project scales up, compilation time does not significantly increase, which greatly enhances the development experience.

Tip

Lazy compilation is only effective for dev builds and does not affect production builds.

Example

Enable lazy compilation

For web targets, Rsbuild enables the imports option by default, which means lazy compilation of dynamically imported modules.

To enable full lazy compilation functionality, set lazyCompilation option to true:

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: true,
  },
};

This is equivalent to the following configuration:

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: {
      imports: true,
      // If there is only one entry, Rsbuild will not enable the entries option by default
      entries: true,
    },
  },
};

Disable lazy compilation

To disable lazy compilation, set lazyCompilation to false:

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: false,
  },
};

Entry modules

Use lazyCompilation.entries to control whether to lazily compile entry modules:

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: {
      entries: true,
    },
  },
};

With the entries option enabled, Rsbuild will not compile all pages when you start the dev server. Instead, it will only compile a specific page when you visit it.

When lazily compiling entry modules, please note:

  • It only applies to multi-page applications (MPA) and does not optimize single-page applications (SPA).
  • When you visit a page, you need to wait for the page to finish compiling before you can see its content.

Async modules

Use lazyCompilation.imports to control whether to lazily compile dynamic imported modules.

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: {
      imports: true,
    },
  },
};

When the imports option is enabled, all async modules will only be compiled when requested. If your project is a single-page application (SPA) and you have split the routes using dynamic import, this will significantly speed up the startup time.

Server URL

Use lazyCompilation.serverUrl to tell the client the server URL that needs to be requested.

For web targets, if lazyCompilation.serverUrl is not explicitly configured, Rsbuild derives the default serverUrl from dev.client when both of the following conditions are met:

When dev.assetPrefix is a relative URL, Rsbuild does not infer serverUrl from dev.client. Lazy compilation requests use the current page origin.

An explicitly configured lazyCompilation.serverUrl always takes priority over the default value inferred from dev.client.

Example:

rsbuild.config.ts
export default {
  dev: {
    lazyCompilation: {
      serverUrl: 'http://localhost:<port>',
    },
  },
};
Tip

Rsbuild will replace the <port> placeholder with the actual port number the server is listening on.

Node targets

Node targets compile eagerly by default. Set dev.lazyCompilation.node: true to defer dynamic imports. Boolean true and options without node: true remain browser-only. Node entries stay eager, and entries: true is rejected. Node lazy compilation requires mode: 'development' and dev.hmr: true. Other modes are rejected because hot updates must preserve the retained runtime.

For example, configure an ES module bundle for an application-owned native runtime:

rsbuild.config.ts
export default {
  output: {
    target: 'node',
    module: true,
    filename: {
      js: '[name].mjs',
    },
  },
  dev: {
    writeToDisk: true,
    lazyCompilation: { node: true },
  },
  tools: {
    rspack: {
      output: { publicPath: 'auto' },
    },
  },
};

The application or framework owns the runtime lifecycle:

  • Load the emitted entry once with native import() or require() and retain that runtime while a lazy import is pending.
  • Expose a bridge from the entry that calls import.meta.webpackHot.check(true) or module.hot.check(true). Invoke it after a successful compilation, when the update files are available. Apply pending revisions sequentially until the runtime's __webpack_hash__ matches the successful compilation's hash. Rsbuild installs the HMR plugin but does not drive hot checks.
  • Handle update failures and dispose of the runtime, requests, and server on shutdown. An update that the runtime cannot accept requires recovery by the application.

Native runtimes need access to emitted chunks and hot-update files. The example writes them to disk and uses publicPath: 'auto' so ESM hot updates resolve relative to the output. For CommonJS output inside a package with "type": "module", use .cjs bundle and async chunk filenames, and set tools.rspack.output.hotUpdateChunkFilename to '[id].[fullhash].hot-update.cjs'.

The Node activation endpoint defaults to an absolute HTTP(S) URL from the dev server's protocol, host, and actual port. It does not use dev.client overrides. An explicit HTTP(S) serverUrl takes precedence and supports <port>. With externally hosted dev middleware, set serverUrl to the reachable host endpoint.

The runtime owner must also define which module accepts an update. A self-accepted module does not notify its parents, so previously returned module references can stay unchanged. A lazy boundary can accept a static dependency and expose a getter that reads the updated binding:

src/boundary.js
import { value } from './value.js';

export const getValue = () => value;

import.meta.webpackHot.accept('./value.js', () => {});

An entry can lazily import this boundary once and call getValue() after an update. The changing value.js module must let the update propagate to the boundary instead of accepting itself.

Rsbuild does not retain or hot update runtimes created by environment.loadBundle. Node output remains excluded from HTTP asset serving. Frameworks must coordinate their acceptance boundaries, route manifests, and loader updates with the retained runtime.

Version history

VersionChanges
v1.3.0Added this option
v1.5.0Changed default value from false to { imports: true, entries: false }
v2.0.13Derived the default serverUrl from dev.client
v2.1.7Limited dev.client inference to dev.assetPrefix: true or an absolute URL