Experiments

该选项赋予用户激活和尝试实验功能的能力。

  • 类型: object

experiments.asyncWebAssembly

  • 类型: boolean
  • 默认值: false

支持基于新规范的 WebAssembly,这使 WebAssembly 模块成为异步模块 当设置 experiments.futureDefaultstrue 时,默认启用此功能。

experiments.incrementalRebuild

启用增量重新编译。当启用此选项,Rspack 在重新编译时会尝试复用上次构建的结果来提升构建速度,支持对不同阶段进行配置,默认为开启状态。

0.5 版本移除该配置并内置开启该功能。

  • 类型: boolean | { make?: boolean, emitAsset?: boolean }
  • 默认值: true

experiments.outputModule

  • 类型: boolean
  • 默认值: false

开启之后,将尽可能输出符合 ECMAScript 语法的代码。例如,使用 import() 加载 chunk,使用 ESM exports 等等。

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

experiments.css

启用原生 CSS 支持和 CSS 相关的 parser 和 generator options:

WARNING

如果你在使用 style-loadercss-loader 请关闭该配置,因为 style-loadercss-loader 和原生 CSS 功能冲突。

experiments.futureDefaults

使用下一个主版本 Rspack 的默认值,并在任何有问题的地方显示警告。

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

experiments.topLevelAwait

开启打包 top level await 的支持,top level await 仅能在 ModuleTypejavascript/esm 的模块中使用。

默认开启,可通过该配置关闭。

experiments.lazyCompilation

  • 类型:
type LazyCompilationOptions =
  | boolean
  | {
      /**
       * 为 entries 启用 lazy compilation
       */
      entries?: boolean;
      /**
       * 为 dynamic imports 启用 lazy compilation
       */
      imports?: boolean;
      /**
       * 指定哪些导入的模块应该被延迟编译
       */
      test?: RegExp | ((m: Module) => boolean);
    };
  • 默认值: false

开启懒编译,这对提高多入口应用(MPA)或大型单页面应用(SPA)的 dev 启动性能会非常有帮助。例如你有二十个入口,只有访问到的入口才会进行构建,或者如果项目中存在非常多的 import(),每一个 import() 所指向的模块都只有在被真正访问到时,才进行构建。

如果设置为 true,则默认会对入口模块以及 import() 指向的模块进行懒编译。你可以通过配置对象形式,来决定是否只对入口或只对 import() 生效。entries 决定是否对入口生效,import() 决定是否对 import() 生效。

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

module.exports = {
  experiments: {
    // 仅在 dev 模式下开启
    lazyCompilation: isDev,
  },
};

除此以外你还可以配置 test 来更细粒度控制对哪些模块进行懒编译。test 可以是一个正则表达式,只对该正则匹配到的模块进行懒编译,test 也可以是一个函数,函数的输入是 Module 类型,返回 boolean 类型,表示是否命中懒编译逻辑。

NOTE

当前 lazy compilation 是对齐 webpack 实现的,并且仍处于实验性阶段。在部分场景下,lazy compilation 可能无法按照预期工作,或是性能提升不明显。

排除 HMR client

如果你未使用 Rspack 的 dev server,而是使用自己的 server 作为开发服务器,一般会在 entry 配置中加入另外的 client 代码来开启 HMR 等能力,那么最好通过配置 test 来将该 client 模块从懒编译模块中排除出去。

如果不排除掉,并且开启 entry 的懒编译,该 client 在第一次访问页面时不会被编译,因此需要一次额外的刷新才能让其真正生效。

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

const options = {
  experiments: {
    lazyCompilation: {
      test(module) {
        const isMyClient = module.nameForCondition().endsWith('dev-client.js');
        // 让 dev-client.js 不被懒编译
        return !isMyClient;
      },
    },
  },
};
const compiler = rspack(options);

new compiler.webpack.EntryPlugin(compiler.context, 'dev-client.js', {
  // name: undefined 代表这是全局 entry,会插入到每一个 entry 前
  name: undefined,
}).apply(compiler);

experiments.rspackFuture

  • 类型: object

  • 默认值: 参考下方各项配置

用于控制是否开启 Rspack 未来的默认行为,详情请参考这里

experiments.rspackFuture.disableTransformByDefault

  • 类型: boolean

  • 引入版本: v0.3.5

  • 默认开启版本: v0.4.0

  • 移除版本: v0.5.0

  • 说明:

    该功能主要对于三类问题进行处理:builtins 代码转换功能,target,自定义 Rule.type

    1. 移除对部分 builtins 功能的支持:

    这部分配置项应当作用于被选中的相应模块,而使用 builtins.(relay|react|emotion|pluginImport|decorator) 则等于是全局开启,这种方案不被推崇,因此将被废弃。

    在开启 disableTransformByDefault 后,上述配置项将失效,迁移指南可以参考 builtin:swc-loader/options.rspackExperiments

    例如我们希望 emotion 的转换被应用于所有 jsx 文件:

    rspack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.jsx$/,
            loader: 'builtin:swc-loader',
            options: {
              jsc: {
                parser: {
                  syntax: "ecmascript",
                  jsx: true
                }
              },
              rspackExperiments: {
                emotion: true // 配置项和原 builtins 保持一致
              }
            }
            type: 'javascript/auto',
          },
        ],
      },
      experiments: {
        rspackFuture: {
          disableTransformByDefault: true
        }
      }
    };

    对于 decorator 的配置项可以在,swc 代码中找到并替换,如 legacyDecoratordecoratorMetadata

    1. target 将不会对用户侧代码做降级

    以往的版本中,我们通常会配置 target: ["web", "es5"] 来生成适用于 web 和降级后的代码。

    现在,当用户开启了 disableTransformByDefault 配置项后,target 仅会被用于控制 runtime 代码(除了用户编写、node_modules 内的 Rspack 生成的代码,例如 chunk 加载等等)

    这和 webpack 的插件化设计思维完成了对齐,你可以使用 builtin:swc-loaderenvtarget 进行迁移, 并精确控制需要转译的模块:

    rspack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'builtin:swc-loader',
            options: {
              jsc: {
                parser: {
                  syntax: "ecmascript"
                },
                target: "es5" // 注意,env 和 jsc.target 不能同时设置
              },
              env: { // 注意,env 和 jsc.target 不能同时设置
                targets: "chrome >= 48"
              }
            }
            type: 'javascript/auto',
          },
        ],
      },
      experiments: {
        rspackFuture: {
          disableTransformByDefault: true
        }
      }
    };

    注意:在未开启 disableTransformByDefault 时,rspack 内置的转译器会对 node_modules 下的所有内容进行转译。 因此在开启了 disableTransformByDefault 后,builtin:swc-loader 配合 exclude: /node_modules/ 需要确保 node_modules 下代码已经完成了降级,否则可能会存在兼容性问题。

    1. 移除了非 webpack 兼容的 Rule.type

    这些类型被移除:

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

    对于 JS 相关的类型仅会保留:

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

    在开启 disableTransformByDefault 后,Rspack 仅支持符合 web 标准的输入,对齐 webpack 的设计理念。

    在我们完成和 webpack 的讨论后,webpack 和 Rspack 将会提供更加开箱即用的配置,以支持非标准的输入,如 TypeScript 等。

    由于目前对于 jsx, tsx, ts 后缀名的文件会隐式地开启转译,因此在开启 disableTransformByDefault 后会提示编译报错,你可以这样完成迁移:

    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

  • 类型: boolean

  • 引入版本: v0.3.5

  • 默认开启版本: v0.4.0

  • 移除版本: v0.5.0

该功能将会开启新版 resolver,新的实现比旧版的 resolver 快了 5 倍。

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

新的 resolver 同时提供了在 tsconfig-paths-webpack-plugin 中定义的tsconfig project references 功能。 具体请参考 resolve API.

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

experiments.rspackFuture.newTreeshaking

  • 类型: boolean
  • 引入版本: v0.4.2
  • 默认开启版本: v0.6.0
  • 移除版本: v0.7.0
WARNING

从 0.7.0 版本开始,newTreeshaking 默认开启并且不能切换回已废弃的老 tree shaking 算法。

该功能启用了与 webpack 相同的新摇树优化实现,可以生成更高效和更小的代码。

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

experiments.rspackFuture.disableApplyEntryLazily

  • 类型: boolean
  • 引入版本: v0.4.5
  • 默认开启版本: v0.5.0
  • 移除版本: v0.6.0

在未开启该功能时,在 compiler.hooks.afterEnvironment 调用之后仍然可以对 options.entry 进行有效的修改。

而在开启该功能后,在 compiler.hooks.afterEnvironment 调用之后不会再进行 options.entry 的有效修改。该行为与 Webpack 一致,所以该配置对于使用 Rspack 开发应用的用户来说基本没有影响,而对于 Rspack 的插件或上层框架开发者需要注意。

一个常见的场景就是在创建 Compiler 之后增加一些入口

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');

在开启该功能后修改将不生效,需要进行如下修改:

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');