Announcing Rspack 0.6

April 10, 2024

Major Feature Updates

Built-in support for mini-css-extract-plugin

Now you can use rspack.CssExtractRspackPlugin as a replacement for mini-css-extract-plugin.

This is very useful in some scenarios, for example when the built-in CSS parser cannot meet your needs, there are more customized CSS Modules names, or you want to use some loaders that depend on the output of css-loader, but still want to extract the CSS into a separate file.

For more details, please see CssExtractRspackPlugin.

const rspack = require('@rspack/core');
module.exports = {
  plugins: [new rspack.CssExtractRspackPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
      },
    ],
  },
};

There is an basic project example.

Enable new tree shaking by default

In Rspack 0.1.0, basic tree shaking functionality was introduced. Due to the initial architecture being unstable, we employed a relatively simplistic approach to implement the basic version of tree shaking (only support unused export variables elimination). However, as rspack's capabilities improved, the architecture gradually stabilized.

The basic tree shaking functionality was insufficient to meet user needs, for example:

  1. It couldn't handle circular references and couldn't provide enough optimization information for other build stages to achieve further optimization (such as mangleExports, concatenateModules, barrel exports optimization).
  2. Some interoperability-related issues often occurred, such as worker-thread modules, Common Js modules, module federation, etc.

To address these issues, we decided to adopt a webpack-like approach, re-implementing the entire optimization process from the bottom up. In version 0.4.2, we introduced the experiments.rspackFuture.newTreeshaking configuration to experimentally enable the new optimization algorithm. After four months of bug fixing and optimization, the new tree shaking algorithm has become relatively stable. Therefore, we've decided to default-enable the new tree shaking algorithm in version 0.6.0.

Breaking Changes

Remove experiments.rspackFuture.disableApplyEntryLazily

The experiments.rspackFuture.disableApplyEntryLazily option has been enabled by default since v0.5.0 and was removed in v0.6.0.

Remove compiler.build and compiler.rebuild

compiler.build and compiler.rebuild are not part of the Webpack public API and have now been removed.

Remove builtins.css, please replace it with the CSS-related module.parser and module.generator options that have been introduced.

Also, starting from v0.6.0, Rspack's experiments CSS will align with webpack's experiments CSS as a target, which means that, like webpack experiments CSS, it will no longer support browsers that do not support CSS variables in the future. Therefore, for those projects that need to use configurations not yet supported by experiments CSS, or need to support older browsers, we recommend migrating to rspack.CssExtractRspackPlugin.

In v0.6.0, we introduced three new types of module.generator and module.parser options: css/auto, css, and css/module, which will only take effect when experiments.css is enabled, checkout this example about how to use it.

In the module.parser options, module types css, css/auto, and css/module all include the namedExports property. It has replaced the builtins.css.namedExports configuration.

For the module.generator options, the css/auto and css/module module types offer the exportsOnly, exportsConvention, and localIdentName properties. The css type includes only the exportsOnly and exportsConvention properties. exportsOnly, exportsConvention, and localIdentName respectively replace builtins.css.modules.exportsOnly, builtins.css.modules.localsConvention, and builtins.css.modules.localIdentName.

In addition, there are some changes to the default values:

  1. The value of exportsConvention has changed from 'asIs', 'camelCaseOnly', etc., to 'as-is', 'camel-case-only', etc., to maintain consistency with webpack experiments css.

  2. With namedExports: false, it is now possible to use default exports, named exports, and namespace exports at the same time; previously, only the default export was supported:

    // Before v0.6.0, only default export was supported
    import classes from './index.module.css';
    
    // Now, in addition to default export, it also supports:
    // Namespace exports
    import * as classes from './index.module.css';
    // Named exports
    import { class1, class2 } from './index.module.css';
    // Default and named exports used together
    import classes, { class1, class2 } from './index.module.css';
  3. The default value of namedExports changed from false to true, meaning you'll have to use a namespace import (like import * as classes from './style.css') or named import (like import { class1 } from './style.css') by default, which will improve future compatibility with native CSS module. And this does not mean you have to migrate all imports at once; you can disable this behavior by setting namedExports: false, and since now namedExports: false also supports named export and namespace export, you can migrate these imports progressively.

  4. The default value of localIdentName has changed from '[path][name][ext]__[local]' in development mode and '[hash]' in production mode to '[uniqueName]-[id]-[local]' in both development and production modes, which will slightly improve the gzip compression size of the CSS output.

  5. The default value of exportsOnly in target: 'node' has changed from false to true.

  6. The default rule type for CSS has changed from css to css/auto. css/auto will automatically process CSS files with .module. or .modules. as infixes as CSS Modules, consistent with css-loader's modules.auto: true, which will simplify the writing rules for using less or sass with CSS Modules.

Upgrade SWC to 0.90.x

Upgraded the Rust crate swc_core to 0.90.x. This will affect users of the SWC Wasm plugin.

Emit warnings when CSS order is inconsistent in multiple chunks

When the order of CSS in multiple chunks is inconsistent, a warning will be issued. For example, if you have two entries, entryA and entryB, where entryA imports a.css and then b.css, while entryB imports b.css and then a.css. When splitChunks conditions are met, a.css and b.css will become a separate chunk. The order of a.css and b.css in this chunk cannot be guaranteed, resulting in the following warning.

WARNING in ⚠ chunk src_a_css-src_b_-5c8c53 [css-extract-rspack-plugin]
  │ Conflicting order. Following module has been added:
  │  * css ./css-loader/dist/cjs.js??ruleSet[1].rules[2].use[1]!./src/a.css
  │ despite it was not able to fulfill desired ordering with these modules:
  │  * css ./css-loader/dist/cjs.js??ruleSet[1].rules[2].use[1]!./src/b.css
  │   - couldn't fulfill desired order of chunk group(s) parent2
  │   - while fulfilling desired order of chunk group(s) parent1

If you are sure that their order inconsistency does not matter, you can ignore this error by configuring ignoreWarnings.

module.exports = {
  ignoreWarnings: [/Conflicting order/],
};

Migration Guide

Apply rspack.CssExtractRspackPlugin

If you have used mini-css-extract-plugin and webpack before, you can simply replace mini-css-extract-plugin by rspack.CssExtractPlugin.

+ const CssExtract = require('@rspack/core').CssExtractRspackPlugin;
- const CssExtract = require('mini-css-extract-plugin');
module.exports = {
  plugins: [new CssExtract()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [CssExtract.loader, 'css-loader'],
      },
    ],
  },
};

Migrate from builtins.css

  1. Use module.parser["css/auto"].namedExports to replace builtins.css.namedExports.
  2. Use module.generator["css/auto"].exportsOnly to replace builtins.css.modules.exportsOnly.
  3. Use module.generator["css/auto"].exportsConvention to replace builtins.css.modules.localsConvention.
  4. Use module.generator["css/auto"].localIdentName to replace builtins.css.modules.localIdentName.

The above occurrences of "css/auto" are the default module type for CSS, which can be modified to "css" or "css/module" as needed.

Add the following configuration to maintain the original default behavior of builtins.css, which can be modified as needed based on the following setup:

module.exports = {
   // ...
+  module: {
+    generator: {
+      "css/auto": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+        localIdentName: isProduction ? '[hash]' : '[path][name][ext]__[local]',
+      },
+      "css": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+      },
+      "css/module": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+        localIdentName: isProduction ? '[hash]' : '[path][name][ext]__[local]',
+      },
+    },
+    parser: {
+      "css/auto": {
+        namedExports: false,
+      },
+      "css": {
+        namedExports: false,
+      },
+      "css/module": {
+        namedExports: false,
+      },
+    },
+  },
}

If it is necessary to configure some modules separately, you can use the rule.parser and rule.generator options in module.rules.

Migrate to compiler.run

compiler.build or compiler.rebuild have been deprecated. Please switch to compiler.run for both building and rebuilding.

Upgrade the SWC plugins

In version 0.6.0, the Rust crate swc_core has been upgraded to 0.90.x. Users of the SWC Wasm plugin need to ensure version consistency with swc_core being used, otherwise, it may lead to unforeseen issues.

For more details, please see this document of SWC.