Experiments

Enable and try out some experimental features.

  • Type: object

experiments.incrementalRebuild

Stability: Removed

Enable incremental rebuild. true will try to reuse the results of the last build when rebuild to improve build speed, supports configuration of different stages, the default is enabled.

0.5 removed this options and internally enabled this feature.

  • Type: boolean | { make?: boolean, emitAsset?: boolean }
  • Default: true

experiments.outputModule

  • Type: boolean
  • Default: true

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

module.exports = {
  experiments: {
    outputModule: true,
  },
};

experiments.css

  • Type: boolean
  • Default: true

Once enabled, Rspack will enable native CSS support, Note that if you're using style-loader and css-loader, you should disable this option because style-loader and css-loader will conflict with native CSS.

experiments.topLevelAwait

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 turned off with this configuration.

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.

experiments.rspackFuture.disableTransformByDefault

  • Type: boolean

  • Introduced in Version: v0.3.5

  • Enabled by Default in Version: v0.4.0

  • Removed in Version: v0.5.0

  • Description:

    This feature primarily addresses three categories of problems: builtins code transformation features, target, and custom Rule.type.

    1. Removal of support for some builtins features:

    These configuration items should apply to the selected corresponding modules. Using builtins.(relay|react|emotion|pluginImport|decorator) is equivalent to enabling them globally. This approach is not recommended, so it will be deprecated.

    After enabling disableTransformByDefault, the aforementioned configuration items will become invalid. For a migration guide, refer to builtin:swc-loader/options.rspackExperiments.

    For instance, if we want the emotion transformation to apply to all jsx files:

    rspack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.jsx$/,
            loader: 'builtin:swc-loader',
            options: {
              jsc: {
                parser: {
                  syntax: "ecmascript",
                  jsx: true
                }
              },
              rspackExperiments: {
                emotion: true // The same as `builtins`
              }
            }
            type: 'javascript/auto',
          },
        ],
      },
      experiments: {
        rspackFuture: {
          disableTransformByDefault: true
        }
      }
    };

    For the decorator configuration, you can find and replace in the SWC code, such as legacyDecorator, decoratorMetadata.

    1. target will not downgrade user-side code

    In previous versions, we typically set target: ["web", "es5"] to produce web-compatible and downgraded code. Now, when the disableTransformByDefault configuration item is enabled, the target will only be used to control runtime code (except for user-written code, rspack generated code within node_modules, like chunk loading, etc.)

    This aligns with webpack's plugin-based design philosophy. You can migrate using builtin:swc-loader's env or target, and precisely control the modules that need to be transpiled:

    rspack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.[cm]?js$/,
            exclude: /node_modules/,
            loader: 'builtin:swc-loader',
            options: {
              jsc: {
                parser: {
                  syntax: "ecmascript"
                },
                target: "es5" // Notice: `jsc.target` and `env` cannot be set at the same time.
              },
              env: { //  Notice: `jsc.target` and `env` cannot be set at the same time.
                targets: "chrome >= 48"
              }
            }
            type: 'javascript/auto',
          },
        ],
      },
      experiments: {
        rspackFuture: {
          disableTransformByDefault: true
        }
      }
    };

    Note: When disableTransformByDefault is not enabled, the rspack's built-in transpiler will transpile all content under node_modules. Therefore, after enabling disableTransformByDefault, with builtin:swc-loader combined with exclude: /node_modules/, ensure the code in node_modules has been downgraded; otherwise, compatibility issues may arise.

    1. Removed non-webpack compatible Rule.type

    These types have been removed:

    • "typescript"
    • "jsx"
    • "tsx"

    For JS-related types, only the following will be retained:

    • "javascript/auto"
    • "javascript/esm"
    • "javascript/dynamic"

    With disableTransformByDefault enabled, rspack will only support input compliant with web standards, aligning with webpack's design philosophy.

    After discussions with webpack, both webpack and rspack will offer more out-of-the-box configurations to support non-standard inputs like TypeScript.

    Since files with the extensions jsx, tsx, and ts are implicitly set for transpilation, an error will be prompted when disableTransformByDefault is enabled. You can migrate like this:

    rspack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.ts$/,
            exclude: /node_modules/,
            loader: 'builtin:swc-loader',
            options: {
              jsc: {
                parser: {
                  syntax: "typescript"
                }
              }
            }
            type: 'javascript/auto',
          },
        ],
        {
          test: /\.tsx$/,
          exclude: /node_modules/,
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              parser: {
                syntax: "typescript",
                tsx: true
              }
            }
          }
          type: 'javascript/auto',
        },
        {
          test: /\.jsx$/,
          exclude: /node_modules/,
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              parser: {
                syntax: "ecmascript",
                jsx: true
              }
            }
          }
        }
      },
      experiments: {
        rspackFuture: {
          disableTransformByDefault: true
        }
      }
    };

experiments.rspackFuture.newResolver

  • Type: boolean
  • Introduced in Version: v0.3.7
  • Enabled by Default in Version: v0.4.0
  • Removed in Version: v0.5.0

This feature enables the new resolver implementation provided by oxc, which is 5 times faster than the previous resolver implementation.

rspack.config.js
module.exports = {
  experiments: {
    rspackFuture: {
      newResolver: true,
    },
  },
};

The new resolver also supports tsconfig project references defined in tsconfig-paths-webpack-plugin. See resolve API for details.

rspack.config.js
module.exports = {
  resolve: {
    tsconfig: {
      configFile: path.resolve(__dirname, './tsconfig.json'),
      references: 'auto'
    },
  }
  experiments: {
    rspackFuture: {
      newResolver: true
    }
  }
}

experiments.rspackFuture.newTreeshaking

  • Type: boolean
  • Default Value: false

This feature enables the new treeshaking implementation the same as webpack, which would generate more efficient and smaller code

rspack.config.js
module.exports = {
  experiments: {
    rspackFuture: {
      newTreeshaking: true,
    },
  },
};

experiments.rspackFuture.disableApplyEntryLazily

  • Type: boolean
  • Introduced in Version: v0.4.5
  • Enabled by Default in Version: v0.5.0
  • Removed in Version: v0.6.0

When this feature is not enabled, options.entry can still make valid changes after compiler.hooks.afterEnvironment is called.

With this feature turned on, options.entry will no longer make valid changes after compiler.hooks.afterEnvironment call. This behavior is consistent with Webpack, so this configuration is unaffected for users developing applications in Rspack, but should be noted by developers of Rspack plugins or upper-level frameworks.

A common scenario is to prepend entries after the Compiler has been created:

const rspack = require('@rspack/core');
const compiler = rspack(options);

function prependEntry(compiler, additionalEntry) {
  for (const key in compiler.options.entry) {
    compiler.options.entry[key].import = [
      additionalEntry,
      ...(compiler.options.entry[key].import || []),
    ];
  }
}

prependEntry(compiler, 'dev-client.js');

Modifications will not take effect when this configuration is turned on, and you need to make the following changes:

const rspack = require('@rspack/core');
const compiler = rspack(options);

function prependEntry(compiler, additionalEntry) {
  new compiler.webpack.EntryPlugin(compiler.context, additionalEntry, {
    name: undefined,
  }).apply(compiler);
}

prependEntry(compiler, 'dev-client.js');