内置 swc-loader

builtin:swc-loaderswc-loader 的 Rust 版本,旨在提供更优的性能,Loader 的配置与 JS 版本的 swc-loader 保持对齐。

示例

如果需要在项目中使用 builtin:swc-loader,可以参考下面的示例进行配置。

TypeScript 转译

比如对 .ts 文件进行转译:

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.ts$/,
  6. exclude: [/node_modules/],
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. jsc: {
  10. parser: {
  11. syntax: 'typescript',
  12. },
  13. },
  14. },
  15. type: 'javascript/auto',
  16. },
  17. ],
  18. },
  19. };

JSX 转译

对 React 的 .jsx 文件进行转译:

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.jsx$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. jsc: {
  10. parser: {
  11. syntax: 'ecmascript',
  12. jsx: true,
  13. },
  14. transform: {
  15. react: {
  16. pragma: 'React.createElement',
  17. pragmaFrag: 'React.Fragment',
  18. throwIfNamespace: true,
  19. development: false,
  20. useBuiltins: false,
  21. },
  22. },
  23. },
  24. },
  25. },
  26. type: 'javascript/auto',
  27. },
  28. ],
  29. },
  30. };

语法降级

SWC 提供了 jsc.targetenv.targets 来指定 JavaScript 语法降级的目标。

jsc.target

jsc.target 用于指定 ECMA 版本,例如 es5es2015es2016 等。

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.js$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. jsc: {
  10. target: 'es2015',
  11. },
  12. // ...other options
  13. },
  14. },
  15. },
  16. ],
  17. },
  18. };

env.targets

env.targets 使用 browserslist 的语法来指定浏览器范围,例如:

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.js$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. env: {
  10. targets: [
  11. 'chrome >= 87',
  12. 'edge >= 88',
  13. 'firefox >= 78',
  14. 'safari >= 14',
  15. ],
  16. },
  17. // ...other options
  18. },
  19. },
  20. },
  21. ],
  22. },
  23. };

TIP

jsc.targetenv.targets 不能同时配置,使用时根据需求选择其中一个即可。

Polyfill 注入

当你在项目中使用高版本的 JavaScript 语法和 API 时,为了让编译后的代码能稳定运行在低版本的浏览器中,通常需要完成两部分降级:语法降级和 polyfill 注入。

SWC 支持注入 core-js 作为 API polyfill,可以通过 env.modeenv.coreJs 来配置:

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.js$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. env: {
  10. mode: 'usage',
  11. coreJs: '3.26.1',
  12. targets: [
  13. 'chrome >= 87',
  14. 'edge >= 88',
  15. 'firefox >= 78',
  16. 'safari >= 14',
  17. ],
  18. },
  19. // ...other options
  20. },
  21. },
  22. },
  23. ],
  24. },
  25. };

类型声明

你可以使用 @rspack/core 导出的 SwcLoaderOptions 类型来开启类型提示:

  • rspack.config.js:
  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.js$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. /** @type {import('@rspack/core').SwcLoaderOptions} */
  9. options: {
  10. // some options
  11. },
  12. },
  13. },
  14. ],
  15. },
  16. };
  • rspack.config.ts:
  1. import type { SwcLoaderOptions } from '@rspack/core';
  2. export default {
  3. module: {
  4. rules: [
  5. {
  6. test: /\.js$/,
  7. use: {
  8. loader: 'builtin:swc-loader',
  9. options: {
  10. // some options
  11. } satisfies SwcLoaderOptions,
  12. },
  13. },
  14. ],
  15. },
  16. };

Options

下面是部分 SWC 配置以及 Rspack 特有配置的介绍,完整选项请参考 SWC 配置

jsc.experimental.plugins

Stability: Experimental

WARNING

Wasm 插件和 SWC 的版本存在一定的绑定关系,需要选择和对应 SWC 版本兼容的 Wasm 插件才能正常执行, selecting-swc-core 里有更多关于如何选择兼容的 Wasm 插件的信息。

Rspack 支持在 builtin:swc-loader 里加载 SWC 的 Wasm 插件, 你可以通过如下配置启用 Wasm 插件

  1. {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.js$/,
  6. use: {
  7. loader: 'builtin:swc-loader',
  8. options: {
  9. jsc: {
  10. experimental: {
  11. plugins: [
  12. [
  13. '@swc/plugin-remove-console',
  14. {
  15. exclude: ['error'],
  16. },
  17. ],
  18. ],
  19. },
  20. },
  21. },
  22. },
  23. },
  24. ];
  25. }
  26. }

这是 Wasm 插件的一个示例

设置缓存目录

当你使用 SWC 的 Wasm 插件时,SWC 默认会生成缓存文件在当前项目的 .swc 目录下,如果你希望调整该目录,可以修改 cacheRoot 配置,如:

  1. const path = require('path');
  2. module.exports = {
  3. module: {
  4. rules: [
  5. {
  6. test: /\.js$/,
  7. use: {
  8. loader: 'builtin:swc-loader',
  9. options: {
  10. jsc: {
  11. experimental: {
  12. cacheRoot: path.join(__dirname, './node_modules/.cache/swc'),
  13. },
  14. },
  15. },
  16. },
  17. },
  18. ],
  19. },
  20. };

rspackExperiments

Rspack 内置的实验性功能。

rspackExperiments.import

Stability: Experimental

移植自 babel-plugin-import,配置基本保持一致。

但不能使用函数进行配置,例如 customNamecustomStyleName 等,这是因为这些函数必须由 Rust 调用,这种调用会造成一些性能劣化,受到 modularize_imports 的启发,简单的函数逻辑其实可以通过模版来代替,因此 customNamecustomStyleName ,这些配置可以传入字符串作为模版来代替函数,提高性能。

我们以下面代码为例说明:

  1. import { MyButton as Btn } from 'foo';

添加以下配置:

rspack.config.js

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. use: 'builtin:swc-loader',
  6. options: {
  7. ...
  8. rspackExperiments: {
  9. import: [{
  10. libraryName: 'foo',
  11. customName: 'foo/es/{{ member }}',
  12. }]
  13. }
  14. }
  15. }
  16. ]
  17. }
  18. };

其中的 {{ member }} 会被替换为相应的引入成员,转换后:

  1. import Btn from 'foo/es/MyButton';

可以看出配置 customName: "foo/es/{{ member }}" 的效果等同于配置 customName: (member) => `foo/es/${member}` ,但是不会有 Node-API 的调用开销。

这里使用到的模版是 handlebars,模版配置中还内置了一些有用的辅助函数,还是以上面的导入语句为例:

配置如下:

rspack.config.js

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. use: 'builtin:swc-loader',
  6. options: {
  7. ...
  8. rspackExperiments: {
  9. import: [{
  10. libraryName: 'foo',
  11. customName: 'foo/es/{{ kebabCase member }}',
  12. }]
  13. }
  14. }
  15. }
  16. ]
  17. }
  18. };

会转换成下面的结果:

  1. import Btn from 'foo/es/my-button';

除了 kebabCase 以外还有 camelCasesnakeCaseupperCaselowerCaselegacyKebabCaselegacySnakeCase 可以使用。

其中 legacyKebabCase/legacySnakeCase 使用跟 babel-plugin-import@1.13.7 之前的版本相同的转换逻辑。

其他配置可以直接查看 babel-plugin-import

再以经典的 4 版本的 ant-design 为例,我们只需要如下配置:

rspack.config.js

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. use: 'builtin:swc-loader',
  6. options: {
  7. ...
  8. rspackExperiments: {
  9. import: [
  10. {
  11. libraryName: 'antd',
  12. style: '{{member}}/style/index.css',
  13. },
  14. ]
  15. }
  16. }
  17. }
  18. ]
  19. }
  20. };

上面的配置会将 import { Button } from 'antd'; 转换成

  1. import Button from 'antd/es/button';
  2. import 'antd/es/button/style/index.css';

然后就可以在页面中看到样式文件自动被引入并且生效了。

当然如果你已经配置了对 less 的支持,也可以直接使用如下配置:

rspack.config.js

  1. module.exports = {
  2. module: {
  3. rules: [
  4. {
  5. use: 'builtin:swc-loader',
  6. options: {
  7. ...
  8. rspackExperiments: {
  9. import: [
  10. {
  11. libraryName: 'antd',
  12. style: true,
  13. },
  14. ]
  15. }
  16. }
  17. }
  18. ]
  19. }
  20. };

上面的配置会将 import { Button } from 'antd'; 转换成:

  1. import Button from 'antd/es/button';
  2. import 'antd/es/button/style';