当前文档中的 SWC 功能已停止迭代,我们更推荐使用 Rspack + SWC 的方案。
请参考「使用 Rspack」了解更多。
SWC (Speedy Web Compiler) 是基于 Rust
语言编写的高性能 JavaScript 和 TypeScript 转译和压缩工具。在 Polyfill 和语法降级方面可以和 Babel 提供一致的能力,并且性能比 Babel 高出一个数量级。
Modern.js 提供了开箱即用的 SWC 插件,可以为你的 Web 应用提供语法降级、Polyfill 以及压缩,并且移植了一些额外常见的 Babel 插件。
在使用 SWC 插件之前,请先了解一下 SWC 插件的适用场景和局限性,以明确你的项目是否需要使用 SWC 插件。
如果你的项目中已经使用了 Rspack 作为打包工具,那么你不需要接入 SWC 插件,因为 Rspack 默认会使用 SWC 进行转译和压缩,各个 SWC 编译能力可以开箱即用。
如果你使用 Rspack 时配置了当前的 SWC 插件,它将不会产生任何效果。
如果你的项目需要注册一些自定义的 Babel 插件,由于 SWC 替代了 Babel 作为转译工具,因此使用 SWC 后,你将无法注册和使用 Babel 插件。
对于大部分常见的 Babel 插件,你可以在 SWC 中找到对应的替代品,比如:
@babel/preset-env
: 使用 presetEnv 代替。@babel/preset-react
: 使用 presetReact 代替。babel-plugin-import
:使用 source.transformImport 代替。babel-plugin-lodash
:使用 extensions.lodash 代替。@emotion/babel-plugin
:使用 extensions.emotion 代替。babel-plugin-styled-components
:使用 extensions.styledComponents 代替。@babel/plugin-react-transform-remove-prop-types
: 使用 reactUtils.removePropTypes 代替。如果你使用了 SWC 尚未支持的 Babel 插件能力,在切换到 SWC 编译后,将无法再使用它们。你可以到 swc-plugins 仓库下通过 issues 进行反馈,我们会评估是否需要内置支持。
在使用 SWC 来代替 terser 和 cssnano 进行代码压缩时,构建产物的体积可能会出现少量变化。在 JavaScript 代码压缩方面,SWC 的压缩率是优于 terser 的;在 CSS 代码压缩方面,SWC 的压缩率稍逊于 cssnano。
对于压缩工具之间的详细对比,可以参考 minification-benchmarks。
Modern.js 框架对 SWC 插件进行了封装,你可以通过以下方式来使用:
首先,你需要执行 pnpm run new
启用 SWC 编译:
执行完成后,你只需在 modern.config.ts
文件中注册 Modern.js 的 SWC 插件,即可启用 SWC 编译和压缩能力。
That's it! 现在你可以在项目中无缝使用 SWC 的转译和压缩能力了。
插件配置在 SWC 配置的基础上,为了简化部分深层配置和为提高开发体验,进行了部分拓展,例如当使用对象形式配置时,可以使用 presetReact
以及 presetEnv
快速配置 react 以及语法降级相关功能,另外不属于插件特有的配置也会直接透传给 swc。
当使用函数形式配置时,则会传入插件内部产出的默认配置,可以对其进行修改或返回新的配置。
对标 @babel/preset-react
。传入的值会与默认配置进行合并。
插件默认会自动根据你的 react
版本确定 runtime
字段,如果 react
版本大于 17.0.0,会设置成 automatic
,否则设置成 classic
。
对标 @babel/preset-env
。传入的值会与默认配置进行合并。
默认配置为:
boolean
或者 terser 中的 compress 配置。{ compress: {}, mangle: true }
。如果配置 false
将不会使用 SWC 的压缩能力,配置 true
会启用默认压缩配置,如果配置是对象,则会与默认配置进行合并。
boolean
true
是否启用 SWC 对 CSS 文件进行压缩,若启用会使得 CSS 压缩性能提高,但压缩率会略微降低。
undefined
对指定文件运用另外的配置。例如需要对 foo.ts
的语法降级成 ie 11,则可以如下配置:
该配置会与默认配置进行合并,并且不会影响到其他文件。
Object
extensions
包含了从 Babel 移植过来的一些插件能力。
一些用于 React
的工具,包括以下配置项:
reactUtils.autoImportReact
boolean
自动引入 React
, import React from 'react'
,用于 jsx
转换使用 React.createElement
。
reactUtils.removeEffect
boolean
移除 useEffect
调用。
reactUtils.removePropTypes
移除 React
组件在运行时的类型判断。移植自 @babel/plugin-react-transform-remove-prop-types。
相应配置和 @babel/plugin-react-transform-remove-prop-types
插件保持一致。
移植自 babel-plugin-lodash,用于自动将 Lodash 的引用转换为按需引入,从而减少打包后的 Lodash 代码大小。
由 Next.js 团队移植自 babel-plugin-styled-components。
由 Next.js 团队移植自 @emotion/babel-plugin。
Modern.js 提供了 source.transformImport 配置项,因此你不需要手动配置 extensions.pluginImport
。
移植自 babel-plugin-import,配置选项保持一致。
一些配置可以传入函数,例如 customName
,customStyleName
等,这些 JavaScript 函数会由 Rust 通过 Node-API 调用,这种调用会造成一些性能劣化。
简单的函数逻辑其实可以通过模版语言来代替,因此customName
,customStyleName
等这些配置除了可以传入函数,也可以传入字符串作为模版来代替函数,提高性能。
我们以下面代码为例说明:
添加以下配置:
其中的 {{ member }}
会被替换为相应的引入成员,转换后:
可以看出配置 customName: "foo/es/{{ member }}"
的效果等同于配置 customName: (member) => `foo/es/${member}`
,但是不会有 Node-API 的调用开销。
这里使用到的模版是 handlebars,模版配置中还内置了一些有用的辅助工具,还是以上面的导入语句为例,配置成:
会转换成下面的结果:
除了 kebabCase
以外还有 camelCase
,snakeCase
,upperCase
,lowerCase
可以使用。
不支持 @babel/plugin-transform-runtime
以及其他自定义的 Babel 插件。