CC 4.0 License

The content of this section is derived from the content of the following links and is subject to the CC BY 4.0 license.

The following contents can be assumed to be the result of modifications and deletions based on the original contents if not specifically stated.

Experiments

Enable and try out some experimental features.

  • Type: object
TIP

In minor releases, Rspack may make changes to the APIs of these experimental features and provide detailed explanations of these changes in the release notes. So if you are using experimental features, please pay attention to the minor release notes.

experiments.asyncWebAssembly

  • Type: boolean
  • Default: false

Support the new WebAssembly according to the updated specification, it makes a WebAssembly module an async module.

rspack.config.mjs
export default {
  experiments: {
    asyncWebAssembly: true,
  },
};

And it is enabled by default when experiments.futureDefaults is set to true.

experiments.outputModule

  • Type: boolean
  • Default: false

Once enabled, Rspack will output ECMAScript module syntax whenever possible. For instance, import() to load chunks, ESM exports to expose chunk data, among others.

rspack.config.mjs
export default {
  experiments: {
    outputModule: true,
  },
};

experiments.css

  • Type: boolean
  • Default: false

Once enabled, Rspack will enable native CSS support, and CSS related parser and generator options.

Basic example:

rspack.config.mjs
export default {
  experiments: {
    css: true,
  },
};

experiments.futureDefaults

  • Type: boolean
  • Default: false

Use defaults of the next major Rspack and show warnings in any problematic places.

rspack.config.mjs
export default {
  experiments: {
    futureDefaults: true,
  },
};

experiments.topLevelAwait

  • Type: boolean
  • Default: true

Enable support for Top-level await, Top-level await can only be used in modules with ModuleType is javascript/esm.

Enabled by default and can be disabled with this configuration:

rspack.config.mjs
export default {
  experiments: {
    topLevelAwait: false,
  },
};

experiments.lazyCompilation

  • Type: boolean | LazyCompilationOptions
  • Default: false
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);
    };
TIP

Check out the guide for a quick start.

Enable lazy compilation, which can greatly improve the dev startup performance of multi-page applications (MPA) or large single-page applications (SPA). For example, if you have twenty entry points, only the accessed entry points will be built. Or if there are many import() statements in the project, each module pointed to by import() will only be built when it is actually accessed.

If set to true, lazy compilation will be applied by default to both entry modules and modules pointed to by import(). You can decide whether it applies only to entries or only to import() through a configuration object. The entries option determines whether it applies to entries, while the import() option determines whether it applies to import().

rspack.config.mjs
const isDev = process.env.NODE_ENV === 'development';

export default {
  experiments: {
    // only enabled in dev mode
    lazyCompilation: isDev,
  },
};

In addition, you can also configure a test parameter for more fine-grained control over which modules are lazily compiled. The test parameter can be a regular expression that matches only those modules that should be lazily compiled. It can also be a function where the input is of type 'Module' and returns a boolean value indicating whether it meets the criteria for lazy compilation logic.

TIP

The current lazy compilation is still in the experimental stage. In some scenarios, lazy compilation might not work as expected, or the performance improvement may be insignificant.

lazyCompilation.client

  • Type: string

Used to override the default lazy compilation client runtime. If you want to customize the logic of the client runtime, you can specify it through this configuration option.

rspack.config.mjs
import path from 'path';

export default {
  experiments: {
    lazyCompilation: {
      client: path.resolve('custom-client.js'),
    },
  },
};

lazyCompilation.serverUrl

  • Type: string

Tells the client the server path that needs to be requested. By default it is empty, in a browser environment it will find the server path where the page is located, but in a node environment you need to explicitly specify a specific path.

rspack.config.mjs
export default {
  experiments: {
    lazyCompilation: {
      serverUrl: 'http://localhost:3000',
    },
  },
};

Exclude HMR client

If you do not use Rspack's own dev server and instead use your own server as the dev server, you generally need to add another client modules in the entry configuration to enable capabilities such as HMR. It is best to exclude these client module from lazy compilation by configuring test.

If not excluded and lazy compilation of entry is enabled, this client will not be compiled when accessing the page for the first time, so an additional refresh is needed to make it take effect.

For example:

rspack.config.mjs
import { rspack } from '@rspack/core';

const options = {
  experiments: {
    lazyCompilation: {
      test(module) {
        const isMyClient = module.nameForCondition().endsWith('dev-client.js');
        // make sure that dev-client.js won't be lazy compiled
        return !isMyClient;
      },
    },
  },
};
const compiler = rspack(options);

new compiler.webpack.EntryPlugin(compiler.context, 'dev-client.js', {
  // name: undefined means this is global entry
  name: undefined,
}).apply(compiler);

experiments.layers

  • Type: boolean
  • Default: false

Controls whether to enable the layer feature. Layers can add an identifier prefix to all modules in a subgraph starting from a module in the module graph, to distinguish them from modules in different layers. For example:

The layer of the index.js module is by default null, and its identifier is ./index.js. If we set layer = 'client' for it, its identifier will become (client)/./index.js. At this point, the index.js modules in these two different layers will be treated as distinct modules, because their unique identifiers are different. As a result, the final output will include the artifacts of both modules.

By default, a module's layer is null, and it will inherit its parent module's layer. You can add a layer to an entry module using entryOptions.layer, and you can add a layer to matched modules using module.rule[].layer. Additionally, you can match based on the parent module's layer using module.rule[].issuerLayer.

rspack.config.mjs
export default {
  experiments: {
    layers: true,
  },
};

experiments.incremental

type Incremental = {
  make?: boolean;
  inferAsyncModules?: boolean;
  providedExports?: boolean;
  dependenciesDiagnostics?: boolean;
  sideEffects?: boolean;
  buildChunkGraph?: boolean;
  moduleIds?: boolean;
  chunkIds?: boolean;
  modulesHashes?: boolean;
  modulesCodegen?: boolean;
  modulesRuntimeRequirements?: boolean;
  chunksRuntimeRequirements?: boolean;
  chunksHashes?: boolean;
  chunksRender?: boolean;
  emitAssets?: boolean;
};

Whether to enable incremental rebuild to speed up the rebuild speed. It is recommended to enable it only during development.

rspack.config.mjs
const isDev = process.env.NODE_ENV === 'development';

export default {
  mode: isDev ? 'development' : 'production',
  experiments: {
    incremental: isDev,
  },
};

true means enable incremental for all stages. false means disable incremental for all stages. Incremental can also be enabled only for specified partial stages:

rspack.config.mjs
export default {
  experiments: {
    // enable incremental for all stages
    incremental: true,
    // disable incremental for all stages
    incremental: false,
    // enable only for specified partial stages
    incremental: {
      make: true,
      emitAssets: true,
    },
  },
};

Currently, incremental for the make and emitAssets stages is enabled by default. This is also the default behavior since Rspack v1.0. As this feature further stabilizes, we will enable incremental for more stages by default.

TIP

This feature is experimental. You can check its relevant progress at rspack#8106. You can also report bugs and any related feedback here.

experiments.parallelCodeSplitting

  • Type: boolean
  • Default: true

Enabling this configuration will activate a new multi-threaded code splitting algorithm. If your project includes many dynamic imports, this can greatly reduce the time spent on the code splitting process. Enabled by default since version 1.3.0.

rspack.config.mjs
export default {
  experiments: {
    parallelCodeSplitting: true,
  },
};

experiments.parallelLoader

  • Type: boolean
  • Default: false

Enable parallel loader execution. You need to manually enable parallel mode for each loader using Rule.use.parallel. When enabled, the corresponding loaders will be executed in worker threads.

rspack.config.mjs
export default {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: 'less-loader',
            parallel: true,
            options: {
              // loader options
            },
          },
        ],
      },
    ],
  },
  experiments: {
    parallelLoader: true,
  },
};

experiments.rspackFuture

  • Type: object

  • Default: See options down below for details

Used to control whether to enable Rspack future default options, check out the details here.

rspackFuture.bundlerInfo

  • Type:

    type BundlerInfo = {
      version?: string,
      bundler?: string,
      force?: ('version' | 'uniqueId')[]boolean;
    };

Used to inject the currently used Rspack information into the generated asset:

  • version: Used to specify the Rspack version, defaults to the version field in @rspack/core/package.json.
  • bundler: Used to specify the name of the packaging tool, defaults to rspack.
  • force: Whether to force the injection of Rspack information, which will be added to chunk as a runtime module, and defaults to true to force injection. An array can be used to select the items to be forced injected.

Disable default injection

The default injection can be disabled by setting force to false. Then injection will only occur when __rspack_version__ and __rspack_unique_id__ are detected in the code:

rspack.config.mjs
export default {
  experiments: {
    rspackFuture: { bundlerInfo: { force: false } },
  },
};

experiments.cache

  • Type: ExperimentCacheOptions

  • Default: production mode is false, development mode is true

type ExperimentCacheOptions =
  | boolean
  | {
      type: 'memory';
    }
  | {
      type: 'persistent';
      buildDependencies?: string[];
      version?: string;
      snapshot?: {
        immutablePaths?: Array<string | RegExp>;
        unmanagedPaths?: Array<string | RegExp>;
        managedPaths?: Array<string | RegExp>;
      };
      storage?: {
        type: 'filesystem';
        directory?: string;
      };
    };

Control experimental caching behavior. This will only work if config.cache is set to true.

Note

In production mode, the default value of config.cache is false, which will cause this configuration item invalid. It is recommended to directly configure config.cache to true.

Disable cache

Configuring experiment.cache to false to disable cache, which is no different from configuring the config.cache to false.

rspack.config.mjs
export default {
  cache: true,
  experiments: {
    cache: false,
  },
};

Memory cache

Configuring experiment.cache to true or { "type": "memory" } to enable memory cache.

rspack.config.mjs
export default {
  cache: true,
  experiments: {
    cache: true,
  },
};

Persistent cache

Configuring experiment.cache to { "type": "persistent" } to enable persistent cache.

rspack.config.mjs
export default {
  cache: true,
  experiments: {
    cache: {
      type: 'persistent',
    },
  },
};

cache.buildDependencies

  • Type: string[]

  • Default: []

cache.buildDependencies is an array of files containing build dependencies, Rspack will use the hash of each of these files to invalidate the persistent cache.

TIP

It's recommended to set cache.buildDependencies: [__filename] in your rspack configuration to get the latest configuration.

rspack.config.mjs
export default {
  cache: true,
  experiments: {
    cache: {
      type: 'persistent',
      buildDependencies: [__filename, path.join(__dirname, './tsconfig.json')],
    },
  },
};

cache.version

  • Type: string

  • Default: ""

Cache versions, different versions of caches are isolated from each other.

Persistent cache invalidation

In addition to buildDependencies and version configurations that affect persistent cache invalidation, Rspack also invalidates persistent cache when the following fields change.

cache.snapshot

Configure snapshot strategy. Snapshot is used to determine which files have been modified during shutdown. The following configurations are supported:

snapshot.immutablePaths
  • Type: (RegExp | string)[]

  • Default: []

An array of paths to immutable files, changes to these paths will be ignored during hot restart.

snapshot.managedPaths
  • Type: (RegExp | string)[]

  • Default: [/\/node_modules\//]

An array of paths managed by the package manager. During hot start, it will determine whether to modify the path based on the version in package.json.

snapshot.unmanagedPaths
  • Type: (RegExp | string)[]

  • Default: []

Specifies an array of paths in snapshot.managedPaths that are not managed by the package manager

cache.storage

  • Type: { type: 'filesystem', directory: string }

  • Default: { type: 'filesystem', directory: 'node_modules/.cache/rspack' }

Configure cache storage. Currently only file system storage is supported. The cache directory can be set through directory. The default is node_modules/.cache/rspack.

rspack.config.mjs
export default {
  cache: true,
  experiments: {
    cache: {
      type: 'persistent',
      storage: {
        type: 'filesystem',
        directory: 'node_modules/.cache/rspack',
      },
    },
  },
};
TIP

Rspack will generate a cache folder in the storage.directory based on config.name, config.mode, the file contents in buildDependencies and version.

Rspack will automatically clean up cache folders that have not been accessed for a long time (7 days) at startup.

Migrating from webpack config

The Rspack cache configuration is different from the webpack cache configuration. You can refer to the following steps to migrate the webpack cache configuration.

  1. According to the cache type, set the Rspack cache type. Continue with the next step for persistent cache, and stop here for other types of cache.
rspack.config.mjs
export default {
- cache: {
-   type: 'filesystem',
- },
+ cache: true,
+ experiments: {
+   cache: {
+     type: 'persistent',
+   },
+ },
};
  1. Migrate cache.buildDependencies
rspack.config.mjs
export default {
- cache: {
-   buildDependencies: {
-     config: [__filename, path.join(__dirname, "package.json")],
-     ts: [path.join(__dirname, "tsconfig.json")]
-   }
- },
  experiments: {
    cache: {
      type: "persistent",
+     buildDependencies: [
+       __filename,
+       path.join(__dirname, "package.json"),
+       path.join(__dirname, "tsconfig.json")
+     ]
    },
  },
};
  1. Migrate cache.version and cache.name
rspack.config.mjs
export default {
- cache: {
-   name: `${config.name}-${config.mode}-${otherFlags}`,
-   version: appVersion
- },
  experiments: {
    cache: {
      type: "persistent",
+     version: `${config.name}-${config.mode}-${otherFlags}-${appVersion}`
    },
  },
};
  1. Migrate snapshot
rspack.config.mjs
export default {
- snapshot: {
-   immutablePaths: [path.join(__dirname, "constant")],
-   managedPaths: [path.join(__dirname, "node_modules")],
-   unmanagedPaths: []
- },
  experiments: {
    cache: {
      type: "persistent",
+     snapshot: {
+       immutablePaths: [path.join(__dirname, "constant")],
+       managedPaths: [path.join(__dirname, "node_modules")],
+       unmanagedPaths: []
+     }
    },
  },
};
  1. Migrate cache.cacheDirectory
rspack.config.mjs
export default {
- cache: {
-   cacheDirectory: path.join(__dirname, "node_modules/.cache/test")
- },
  experiments: {
    cache: {
      type: "persistent",
+     storage: {
+       type: "filesystem",
+       directory: path.join(__dirname, "node_modules/.cache/test")
+     }
    },
  },
};

Sample migration code:

function transform(webpackConfig, rspackConfig) {
  rspackConfig.experiments = rspackConfig.experiments || {};
  if (webpackConfig.cache === undefined) {
    webpackConfig.cache = webpackConfig.mode === 'development';
  }
  // 1. if using disable cache, just set `experiments.cache` = false
  if (!webpackConfig.cache) {
    rspackConfig.experiments.cache = false;
    return;
  }
  // 2. if using memory cache, just set `experiments.cache` = true
  if (webpackConfig.cache === true || webpackConfig.cache.type === 'memory') {
    rspackConfig.experiments.cache = true;
    return;
  }
  // 3. using persistent cache, set `experiments.cache` = { type: "persistent" }
  rspackConfig.experiments.cache = { type: 'persistent' };
  // 4. building `experiments.cache` from webpack config
  rspackConfig.experiments.cache.buildDependencies = Object.values(
    webpackConfig.cache.buildDependencies || {},
  ).flat();
  rspackConfig.experiments.cache.version = [
    webpackConfig.cache.name,
    webpackConfig.cache.version,
  ].join();
  rspackConfig.experiments.cache.snapshot = {
    immutablePaths: webpackConfig.snapshot?.immutablePaths,
    managedPaths: webpackConfig.snapshot?.managedPaths,
    unmanagedPaths: webpackConfig.snapshot?.unmanagedPaths,
  };
  rspackConfig.experiments.cache.storage = {
    type: 'filesystem',
    directory: webpackConfig.cache?.cacheDirectory,
  };
}

experiments.buildHttp

  • Type: HttpUriOptions
  • Default: undefined
type HttpUriOptions = {
  /**
   * A list of allowed URIs
   */
  allowedUris: (string | RegExp)[];
  /**
   * Define the location to store the lockfile
   */
  lockfileLocation?: string;
  /**
   * Define the location for caching remote resources
   */
  cacheLocation?: string | false;
  /**
   * Detect changes to remote resources and upgrade them automatically
   * @default false
   */
  upgrade?: boolean;
  /**
   * Custom http client
   */
  httpClient?: (
    url: string,
    headers: Record<string, string>,
  ) => Promise<{
    status: number;
    headers: Record<string, string>;
    body: Buffer;
  }>;
};

After enabling this feature, Rspack can build remote resources that start with the http(s): protocol. Rspack will download the resources to the local machine and then bundle them.

By default, Rspack will generate rspack.lock and rspack.lock.data in the context folder as the locations of the Lockfile and the cache respectively. You can also configure them through lockfileLocation and cacheLocation.

NOTE

You should commit the files at lockfileLocation and cacheLocation to the version control system so that no network requests will be made during the production build.

For example:

rspack.config.mjs
export default {
  experiments: {
    buildHttp: {
      allowedUris: ['https://'],
      lockfileLocation: path.join(__dirname, 'my_project.lock'),
      cacheLocation: path.join(__dirname, 'my_project.lock.data'),
    },
  },
};

With this feature enabled, you can import modules directly from URLs:

// Import from a remote URL
import { something } from 'https://example.com/module.js';

// Or import assets
import imageUrl from 'https://example.com/image.png';