Experiments

实验性功能:该选项通过此配置项可以开启并试用一些实验的功能。

  • 类型: object

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.topLevelAwait

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

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

experiments.lazyCompilation

  • 类型:
type LazyCompilationOptions =
  | boolean
  | {
      entries?: boolean;

      imports?: boolean;

      test?: RegExp | ((m: Module) => boolean);
    };
  • 默认值: false

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

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

除此以外你还可以配置 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');