话说最近本来在倒腾 Prisma 和 Graphql ,可是用 vite 做一个前端示例的时候,偏偏被一个蛋疼的问题卡住了,不得已只好重新用 webpack ,正好试试 SWC。
严格论,SWC 是 babel 的取代者,等量对比的应该是 SWC vs esbuild。
SWC
Rust-based platform for the Web
SWC 是一个可扩展的基于 Rust 的平台,适用于下一代快速开发工具。 它被 Next.js、Parcel 和 Deno 等工具以及 Vercel、ByteDance、腾讯、Shopify 等公司使用。
SWC 可用于编译和捆绑。 对于编译,它使用现代 JavaScript 功能获取 JavaScript / TypeScript 文件,并输出所有主流浏览器都支持的有效代码。
.swcrc 编译配置
SWC 开箱即用,无需定制。 或者,您可以覆盖配置。 以下是默认值:
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": false,
"dynamicImport": false,
"privateMethod": false,
"functionBind": false,
"exportDefaultFrom": false,
"exportNamespaceFrom": false,
"decorators": false,
"decoratorsBeforeExport": false,
"topLevelAwait": false,
"importMeta": false
},
"transform": null,
"target": "es5",
"loose": false,
"externalHelpers": false,
// Requires v1.2.50 or upper and requires target to be es2016 or upper.
"keepClassNames": false
}
}
jsc.externalHelpers
{
"jsc": {
"externalHelpers": true
}
}
输出代码可能依赖于辅助函数来支持目标环境。 默认情况下,辅助函数会内联到需要的输出文件中。
您可以通过启用 externalHelpers
来使用来自外部模块的帮助程序,帮助程序代码将由来自 node_modules/@swc/helpers
的输出文件导入。
捆绑时,此选项将大大减少您的文件大小。
除了 @swc/core
之外,您还必须添加 @swc/helpers
作为依赖项。
jsc.parser
typescript
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": false,
"dynamicImport": false
}
}
}
ecmascript
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": false,
"dynamicImport": false,
"privateMethod": false,
"functionBind": false,
"classPrivateProperty": false,
"exportDefaultFrom": false,
"exportNamespaceFrom": false,
"decorators": false,
"decoratorsBeforeExport": false,
"importMeta": false
}
}
}
jsc.target
Starting from @swc/core
v1.0.27, you can specify the target environment by using the field.
{
"jsc": {
// Disable es3 / es5 / es2015 transforms
"target": "es2016"
}
}
jsc.loose
Starting from @swc/core
v1.1.4, you can enable "loose" transformations by enabling jsc.loose
which works like babel-preset-env
loose mode.
{
"jsc": {
"loose": true
}
}
参考:Babel 6: loose mode (2ality.com)
ES Class 代码
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return `(${this.x}, ${this.y})`; } }
正常模式
"use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); // (A) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Point = (function () { function Point(x, y) { _classCallCheck(this, Point); this.x = x; this.y = y; } _createClass(Point, [{ key: "toString", value: function toString() { return "(" + this.x + ", " + this.y + ")"; } }]); return Point; })();
Loose 模式
"use strict"; function _classCallCheck(instance, Constructor) { ··· } var Point = (function () { function Point(x, y) { _classCallCheck(this, Point); this.x = x; this.y = y; } Point.prototype.toString = function toString() { // (A) return "(" + this.x + ", " + this.y + ")"; }; return Point; })();
jsc.transform
{
"jsc": {
"transform": {
"react": {
"pragma": "React.createElement",
"pragmaFrag": "React.Fragment",
"throwIfNamespace": true,
"development": false,
"useBuiltins": false
},
"optimizer": {
"globals": {
"vars": {
"__DEBUG__": "true"
}
}
}
}
}
}
jsc.transform.legacyDecorator
You can use the legacy (stage 1) class decorators syntax and behavior.
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"decorators": true
},
"transform": {
"legacyDecorator": true
}
}
}
jsc.transform.decoratorMetadata
This feature requires v1.2.13+
.
If you are using typescript and decorators with emitDecoratorMetadata
enabled, you can use swc
for faster iteration:
{
"jsc": {
"parser": {
"syntax": "typescript",
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
}
}
}
jsc.transform.react
jsc.transform.react.runtime
可能的值: automatic
, classic
. 这会影响 JSX 源代码的编译方式。
- Use
runtime: automatic
to use a JSX runtime module (e.g.react/jsx-runtime
introduced in React 17). - Use
runtime: classic
to useReact.createElement
instead - with this option, you must ensure thatReact
is in scope when using JSX.
jsc.transform.react.importSource
- Defaults to
react
. - When using
runtime: automatic
, determines the runtime library to import. - This option can be overrided with
@jsxImportSource foo
.
jsc.transform.react.pragma
- Defaults to
React.createElement
. - When using
runtime: classic
, replaces the function used when compiling JSX expressions. - This option can be overrided with
@jsx foo
.
jsc.transform.react.pragmaFrag
- Defaults to
React.Fragment
- Replace the component used when compiling JSX fragments.
- This option can be overrided with
@jsxFrag foo
.
jsc.transform.react.throwIfNamespace
Toggles whether or not to throw an error if an XML namespaced tag name is used. For example: <f:image />
Though the JSX spec allows this, it is disabled by default since React's JSX does not currently have support for it.
jsc.transform.react.development
Toggles debug props __self
and __source
on elements generated from JSX, which are used by development tooling such as React Developer Tools.
This option is set automatically based on the Webpack mode
setting when used with swc-loader
. See Using swc with webpack.
jsc.transform.react.useBuiltins
Use Object.assign()
instead of _extends
. Defaults to false.
jsc.transform.react.refresh
Enable react-refresh related transform. Defaults to false
as it's considered experimental.
Pass refresh: true
to enable this feature, or an object with the following:
interface ReactRefreshConfig {
refreshReg: String;
refreshSig: String;
emitFullSignatures: boolean;
}
jsc.transform.constModules
{
"jsc": {
"transform": {
"constModules": {
"globals": {
"@ember/env-flags": {
"DEBUG": "true"
},
"@ember/features": {
"FEATURE_A": "false",
"FEATURE_B": "true"
}
}
}
}
}
}
Then, source code like:
import { DEBUG } from "@ember/env-flags";
import { FEATURE_A, FEATURE_B } from "@ember/features";
console.log(DEBUG, FEATURE_A, FEATURE_B);
is transformed to:
console.log(true, false, true);
jsc.transform.optimizer
SWC 优化器假设:
- 它是一个模块或包装在一个 iife 中。
- 访问(获取)全局变量没有副作用。 它与 google 闭包编译器的假设相同。
- You don't add fields to literals like a numeric literal, regular expression or a string literal.
- 文件以 gzip 格式提供。
SWC 不会专注于减少非 gzip 压缩文件的大小。
将此设置为 undefined
会跳过优化器通道。
jsc.transform.optimizer.simplify
Requires
v1.2.101+
您可以将其设置为 false
以在跳过优化时使用 inline_globals
。
{
"jsc": {
"transform": {
"optimizer": {
"simplify": false,
"globals": {
"vars": {
"__DEBUG__": "true"
}
}
}
}
}
}
jsc.transform.optimizer.globals
Requires
v1.2.101+
vars
- Variables to inline.typeofs
- If you set{ "window": "object" }
,typeof window
will be replaced with"object"
.
{
"jsc": {
"transform": {
"optimizer": {
"globals": {
"vars": {
"__DEBUG__": "true"
}
}
}
}
}
}
Then, you can use it like npx swc '__DEBUG__' --filename input.js
.
jsc.transform.optimizer.jsonify
Requires
v1.1.1+
minCost
- 如果解析纯对象文字的成本大于此值,则将对象文字转换为JSON.parse('{"foo": "bar"}')
。 默认为 1024。
{
"jsc": {
"transform": {
"optimizer": {
"jsonify": {
"minCost": 0
}
}
}
}
}
This will change all pure object literals to JSON.parse("")
.
jsc.keepClassNames
Requires
v1.2.50+
and target to be es2016 or higher
启用此选项将使 swc 保留原始类名。
jsc.paths
Requires
v1.2.62+
语法与 tsconfig.json
相同:了解更多。
Requires jsc.baseUrl
. See below.
jsc.baseUrl
原文:TypeScript: Documentation - Module Resolution (typescriptlang.org)
Base URL
Using a
baseUrl
is a common practice in applications using AMD module loaders where modules are “deployed” to a single folder at run-time. The sources of these modules can live in different directories, but a build script will put them all together.Setting
baseUrl
informs the compiler where to find modules. All module imports with non-relative names are assumed to be relative to thebaseUrl
.Value of baseUrl is determined as either:
- value of baseUrl command line argument (if given path is relative, it is computed based on current directory)
- value of baseUrl property in ‘tsconfig.json’ (if given path is relative, it is computed based on the location of ‘tsconfig.json’)
Note that relative module imports are not impacted by setting the baseUrl, as they are always resolved relative to their importing files.
You can find more documentation on baseUrl in RequireJS and SystemJS documentation.
Path mapping
Sometimes modules are not directly located under baseUrl. For instance, an import to a module
"jquery"
would be translated at runtime to"node_modules/jquery/dist/jquery.slim.min.js"
. Loaders use a mapping configuration to map module names to files at run-time, see RequireJs documentation and SystemJS documentation.The TypeScript compiler supports the declaration of such mappings using
paths
property intsconfig.json
files. Here is an example for how to specify thepaths
property forjquery
.{ "compilerOptions": { "baseUrl": ".", // This must be specified if "paths" is. "paths": { "jquery": ["node_modules/jquery/dist/jquery"] // This mapping is relative to "baseUrl" } } }
Please notice that
paths
are resolved relative tobaseUrl
. When settingbaseUrl
to another value than"."
, i.e. the directory oftsconfig.json
, the mappings must be changed accordingly. Say, you set"baseUrl": "./src"
in the above example, then jquery should be mapped to"../node_modules/jquery/dist/jquery"
.Using
paths
also allows for more sophisticated mappings including multiple fall back locations. Consider a project configuration where only some modules are available in one location, and the rest are in another. A build step would put them all together in one place. The project layout may look like:projectRoot ├── folder1 │ ├── file1.ts (imports 'folder1/file2' and 'folder2/file3') │ └── file2.ts ├── generated │ ├── folder1 │ └── folder2 │ └── file3.ts └── tsconfig.json
The corresponding
tsconfig.json
would look like:{ "compilerOptions": { "baseUrl": ".", "paths": { "*": ["*", "generated/*"] } } }
This tells the compiler for any module import that matches the pattern
"*"
(i.e. all values), to look in two locations:
"*"
: meaning the same name unchanged, so map<moduleName>
=><baseUrl>/<moduleName>
"generated/*"
meaning the module name with an appended prefix “generated”, so map<moduleName>
=><baseUrl>/generated/<moduleName>
Following this logic, the compiler will attempt to resolve the two imports as such:
import ‘folder1/file2’:
- pattern ’*’ is matched and wildcard captures the whole module name
- try first substitution in the list: ’*’ ->
folder1/file2
- result of substitution is non-relative name - combine it with baseUrl ->
projectRoot/folder1/file2.ts
.- File exists. Done.
import ‘folder2/file3’:
- pattern ’*’ is matched and wildcard captures the whole module name
- try first substitution in the list: ’*’ ->
folder2/file3
- result of substitution is non-relative name - combine it with baseUrl ->
projectRoot/folder2/file3.ts
.- File does not exist, move to the second substitution
- second substitution ‘generated/*’ ->
generated/folder2/file3
- result of substitution is non-relative name - combine it with baseUrl ->
projectRoot/generated/folder2/file3.ts
.- File exists. Done.
jsc.minify
Requires
v1.2.67+
See the documentation for minification for more details.
原文:TypeScript: Documentation - Module Resolution (typescriptlang.org)
Minification
🚧
This feature is still under construction. We are working on making the smallest bundle size possible, without breaking changes.
Starting with
v1.2.67
, you can configure SWC to minify your code by enablingminify
in your.swcrc
file:{ // Enable minification "minify": true, // Optional, configure minifcation options "jsc": { "minify": { "compress": { "unused": true }, "mangle": true } } }
Configuration
jsc.minify.compress
Type:
boolean | object
.Similar to the compress option of
terser
.{ "jsc": { "minify": { "compress": true // equivalent to {} } } }
arguments
, defaults tofalse
.arrows
, defaults totrue
.booleans
, defaults totrue
.booleans_as_integers
, defaults tofalse
.collapse_vars
, defaults totrue
.comparisons
, defaults totrue
.computed_props
, defaults tofalse
.conditionals
, defaults tofalse
.dead_code
, defaults tofalse
.defaults
, defaults totrue
.directives
, defaults tofalse
.drop_console
, defaults tofalse
.drop_debugger
, defaults totrue
.ecma
, defaults to5
.evaluate
, defaults totrue
.global_defs
, defaults to{}
.hoist_funs
, defaults tofalse
.hoist_props
, defaults totrue
.hoist_vars
, defaults tofalse
.ie8
, Ignored.if_return
, defaults totrue
.inline
, defaults to ``.join_vars
, defaults totrue
.keep_classnames
, defaults tofalse
.keep_fargs
, defaults tofalse
.keep_infinity
, defaults tofalse
.loops
, defaults totrue
.negate_iife
, defaults totrue
.passes
, defaults to0
, which means no limit.properties
, defaults totrue
.pure_getters
, defaults to ``.pure_funcs
, defaults to[]
. Type is an array of string.reduce_funcs
, defaults tofalse
.reduce_vars
, defaults tofalse
.sequences
, defaults totrue
.side_effects
, defaults totrue
.switches
, defaults tofalse
.top_retain
, defaults to ``.toplevel
, defaults to ``.typeofs
, defaults totrue
.unsafe
, defaults tofalse
.unsafe_arrows
, defaults tofalse
.unsafe_comps
, defaults tofalse
.unsafe_Function
, defaults tofalse
.unsafe_math
, defaults tofalse
.unsafe_symbols
, defaults tofalse
.unsafe_methods
, defaults tofalse
.unsafe_proto
, defaults tofalse
.unsafe_regexp
, defaults tofalse
.unsafe_undefined
, defaults tofalse
.unused
, defaults totrue
.module
, Ignored. Currently, all files are treated as module.
jsc.minify.mangle
Type:
boolean | object
.Similar to the mangle option of
terser
.{ "jsc": { "minify": { "mangle": true // equivalent to {} } } }
properties
, Defaults tofalse
, andtrue
is identical to{}
.topLevel
, Defaults tofalse
. Aliased astoplevel
for compatibility withterser
.keepClassnames
, Defaults tofalse
. Aliased askeep_classnames
for compatibility withterser
.keepFnames
, Defaults tofalse
.keepPrivateProps
, Defaults tofalse
. Aliased askeep_private_props
for compatibility withterser
.reserved
, Defaults to[]
ie8
, Ignored.safari10
, Not implemented yet.@swc/core Usage
swc.minify(code, options)
This API is asynchronous and all of parsing, minification, and code generation will be done in background thread. The
options
argument is same asjsc.minify
object. For example:import swc from "@swc/core"; const { code, map } = await swc.minify( "import foo from '@src/app'; console.log(foo)", { compress: false, mangle: true, } ); expect(code).toMatchInlineSnapshot(`"import a from'@src/app';console.log(a);"`);
Returns
Promise<{ code: string, map: string }>
.swc.minifySync(code, options)
This API exists on
@swc/core
,@swc/wasm
,@swc/wasm-web
.import swc from "@swc/core"; const { code, map } = swc.minifySync( "import foo from '@src/app'; console.log(foo)", { compress: false, mangle: true, } ); expect(code).toMatchInlineSnapshot(`"import a from'@src/app';console.log(a);"`);
Returns
{ code: string, map: string }
.APIs for WebAssembly
Replacing Terser
您可以通过 yarn resolutions 减少构建时间并覆盖 Terser,而无需库来更新它们的依赖项。 示例
package.json
将包括:{ "resolutions": { "terser": "npm:@swc/core" } }
这将对所有嵌套依赖项使用 SWC 缩小器而不是 Terser。 确保删除锁定文件并重新安装依赖项。
$ rm -rf node_modules yarn.lock $ yarn
jsc.experimental
Currently, there are no experimental options.
多个入口
Requires
v1.0.47+
[
{
"test": ".*.js$",
"module": {
"type": "commonjs"
}
},
{
"test": ".*.ts$",
"module": {
"type": "amd"
}
}
]
这使得 SWC 将 JavaScript 文件编译为 CommonJS 模块,并将 TypeScript 文件编译为 AMD 模块。
请注意,test
选项只能用于转编译 typescript 文件,例如
{
"test": ".*.ts$",
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
}
}
}
test
Type: Regex / Regex[]
{
"test": ".*.ts$",
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
}
}
}
exclude
Type: Regex / Regex[]
{
"exclude": [".*.js$", ".*.map$"],
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
}
}
}
sourceMaps
Requires
v1.2.50+
Enable source map by adding sourceMaps: true
or sourceMaps: 'inline'
to the .swcrc
.
{
"sourceMaps": true
}
inlineSourcesContent
Requires
v1.2.101+
默认为 true
。 如果要让 swc
将文件内容存储到 sourcemap 中,可以将 inlineSourcesContent
设置为 true
。
{
"sourceMaps": true,
"inlineSourcesContent": true
}
浏览器支持
从 v1.1.10
开始,您现在可以使用 browserslist
自动配置支持的浏览器。
Usage
First, install browserslist
. Then, update your .swcrc
:
{
"env": {
"targets": {
"chrome": "79"
},
"mode": "entry",
"coreJs": 3
}
}
Options
browserslist
If you want to use browserlists with SWC, omit targets
in your .swcrc
:
{
"env": {
"coreJs": 3
}
}
browserlists
can be configured in multiple ways:
.browserslistrc
browserslist
field in package.json
You can use path to specify a custom path to load these configuration files.
targets
string | Array<string> | { [string]: string }
, defaults to {}
.
Describes the environments you support/target for your project. This can either be a browserslist-compatible query:
{
"env": {
"targets": "> 0.25%, not dead"
}
}
Or an object of minimum environment versions to support:
{
"env": {
"targets": {
"chrome": "58",
"ie": "11"
}
}
}
Example environments:
chrome
opera
edge
firefox
safari
ie
ios
android
node
electron
If targets
is not specified, SWC uses browserslist
to get target information.
path
string
, defaults to current directory.path
specifies the directory to load thebrowserslist
module and any browserslist configuration files. For example,.browserslistrc
orbrowserslist
field in package.json. This can be useful if your build system isn't in the root of your project.
mode
string
, defaults toundefined
.- Possible values:
usage
,entry
,undefined
(this matchesuseBuiltIns
from Babel)
⚠️ The usage
mode is currently not as efficient as Babel, yet.
skip
Define ES features to skip to reduce bundle size. For example, your .swcrc
could be:
{
"env": {
"skip": ["core-js/modules/foo"]
}
}
Additional Options
debug
: (boolean) defaults tofalse
.dynamicImport
: (boolean) defaults tofalse
.loose
: (boolean) defaults tofalse
. Enable loose transformations for any plugins that allow them.include
: (string[]) can be acore-js
module (es.math.sign
) or an SWC pass (transform-spread
).exclude
: (string[]) can be acore-js
module (es.math.sign
) or an SWC pass (transform-spread
).coreJs
: (string) defaults toundefined
. The version ofcore-js
to use.shippedProposals
: (boolean) defaults tofalse
.forceAllTransforms
: (boolean) defaults tofalse
. Enable all possible transforms.
Modules
SWC can transpile your code using ES Modules to CommonJS or UMD/AMD. By default, module statements will remain untouched.
CommonJS
To emit a CommonJS module, change the type
in .swcrc
:
{
"module": {
"type": "commonjs",
// These are defaults.
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
ES6
To emit a ES6 module, change the type
in .swcrc
:
{
"module": {
"type": "es6",
// These are defaults.
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
AMD
To emit an AMD module, change the type
in .swcrc
:
{
"module": {
"type": "amd",
// Optional. If specified, swc emits named AMD module.
"moduleId": "foo",
// These are defaults.
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
UMD
To emit an UMD module, change the type
in .swcrc
:
{
"module": {
"type": "umd",
"globals": {},
// These are defaults.
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
Shared Options
These options are shared by commonjs
/ es6
/ umd
/ amd
inside .swcrc
:
{
"module": {
// You can specify "commonjs", "es6", "amd", "umd"
"type": "commonjs",
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false,
"ignoreDynamic": false
}
}
strict
默认为false
。 默认情况下,当使用 SWC 导出时,会导出不可枚举的 __esModule
属性。 在某些情况下,此属性用于确定导入是默认导出还是包含默认导出。默认为“假”。 默认情况下,当使用 SWC 导出时,会导出不可枚举的 __esModule
属性。 在某些情况下,此属性用于确定导入是默认导出还是包含默认导出。
要防止 __esModule
属性被导出,您可以将 strict 选项设置为 true
。
strictMode
Defaults to true
. If true, swc emits 'use strict' directive.
lazy
默认为“假”。 此选项将 Babel 编译的 import
语句更改为在首次使用导入的绑定时进行延迟评估。 这可以改善模块的初始加载时间,因为有时完全不需要预先评估依赖项。 在实现库模块时尤其如此。
lazy
的值有几个可能的影响:
false
- 没有任何导入模块的延迟初始化。true
- 不要惰性初始化本地./foo
导入,而是惰性初始化foo
依赖项。 本地路径更可能具有循环依赖,如果延迟加载可能会中断,因此默认情况下它们不是惰性的,而独立模块之间的依赖很少是循环的。Array<string>
- 使用与给定字符串之一匹配的源来延迟初始化所有导入。
导入永远不会惰性的两种情况是:
import "foo";
Side-effect imports are automatically non-lazy since their very existence means that there is no binding to later kick-off initialization.export from "foo"
Re-exporting all names requires up-front execution because otherwise there is no way to know what names need to be exported.
noInterop
默认为false
。 默认情况下,当使用带有 swc 的导出时,会导出一个不可枚举的 __esModule 属性。 然后,此属性用于确定导入是默认导出还是包含默认导出。
在不需要自动展开默认值的情况下,您可以将 noInterop 选项设置为 true 以避免使用 interopRequireDefault 帮助器(如上面的内联形式所示)。
ignoreDynamic
如果设置为 true
,将保留动态导入。
打包配置
🚧 此功能仍在建设中。
SWC 能够将多个 JavaScript 或 TypeScript 文件捆绑为一个。
此功能当前命名为 spack
,但在 v2
中将重命名为 swcpack
。 spack.config.js
将被 swcpack.config.js
弃用。
查看 打包的基本示例。
Configuration
You can configure bundling using spack.config.js
with similar options to webpack. In the future, we are exploring a webpack compatible plugin system.
// spack.config.js
module.exports = {
entry: {
web: __dirname + "/src/index.ts",
},
output: {
path: __dirname + "/lib",
},
};
Note: CommonJS is currently required. In the future, ES Modules will be supported.
如果您想要自动完成或类型检查配置,您可以使用来自 @swc/core/spack
的 config
函数包装导出。 这是一个带有类型注释的标识函数。
const { config } = require("@swc/core/spack");
module.exports = config({
entry: {
web: __dirname + "/src/index.ts",
},
output: {
path: __dirname + "/lib",
},
});
mode
Possible values: production
, debug
, none
.
Currently this value is not used, but it will behave similarly to webpack.
entry
确定打包的入口。 您可以指定一个文件或包名称到文件路径的映射。
注意:目前这应该是绝对路径。 您可以使用
__dirname
创建一个。未来,SWC 将支持使用相对路径,并将解析相对于
spack.config.js
的文件。
output
You can change destination directory of the bundler using output
.
const { config } = require("@swc/core/spack");
module.exports = config({
output: {
path: __dirname + "/lib",
// Name is optional.
name: "index.js",
},
});
options
Used to control the behavior of SWC. This field is optional.
Migrating from Babel
SWC 的 编译 旨在支持所有 ECMAScript 功能。 SWC CLI 旨在替代 Babel:
$ npx babel # old
$ npx swc # new
Babel 也快有 10 年的历史了,终于也快到他寿终正寝的时候了 —— 他可能没有死,但是在用户的心中已经死了。人们早就翘首期盼着类似 SWC 这样的产物出现。
只是从今天的情况看,SWC 恐怕很难能撑过下一个 10 年(但愿回来打脸)。且不说眼下还有 deno wasmer 这些奇行种的存在。
Comparison
This table outlines the differences between SWC and Babel.
babel package name | swc |
---|---|
babel-plugin-external-helpers | ✔️ |
babel-plugin-proposal-async-generator-functions | ✔️ |
babel-plugin-proposal-class-properties | ✔️ |
babel-plugin-proposal-decorators | ✔️ |
babel-plugin-proposal-do-expressions | ❌ (stage 1) |
babel-plugin-proposal-dynamic-import | ✔️ |
babel-plugin-proposal-export-default-from | ✔️ |
babel-plugin-proposal-export-namespace-from | ✔️ |
babel-plugin-proposal-function-bind | ❌ (stage 0) |
babel-plugin-proposal-function-sent | ❌ (stage 2) |
babel-plugin-proposal-json-strings | ✔️ |
babel-plugin-proposal-logical-assignment-operators | ❌ (stage 1) |
babel-plugin-proposal-nullish-coalescing-operator | ✔️ |
babel-plugin-proposal-numeric-separator | ✔️ |
babel-plugin-proposal-object-rest-spread | ✔️ |
babel-plugin-proposal-optional-catch-binding | ✔️ |
babel-plugin-proposal-optional-chaining | ✔️ |
babel-plugin-proposal-partial-application | ❌ (stage 1) |
babel-plugin-proposal-pipeline-operator | ❌ (stage 0) |
babel-plugin-proposal-private-methods | ✔️ |
babel-plugin-proposal-throw-expressions | ❌ (stage 2) |
babel-plugin-proposal-unicode-property-regex | ❌ |
babel-plugin-syntax-async-generators | ✔️ |
babel-plugin-syntax-bigint | ✔️ |
babel-plugin-syntax-class-properties | ✔️ |
babel-plugin-syntax-decorators | ✔️ |
babel-plugin-syntax-do-expressions | ❌ (stage 1) |
babel-plugin-syntax-dynamic-import | ✔️ |
babel-plugin-syntax-export-default-from | ✔️ |
babel-plugin-syntax-export-namespace-from | ✔️ |
babel-plugin-syntax-flow | ❌ |
babel-plugin-syntax-function-bind | ❌ (stage 0) |
babel-plugin-syntax-function-sent | ❌ (stage 2) |
babel-plugin-syntax-import-meta | ❌ (stage 3, wip) |
babel-plugin-syntax-json-strings | ✔️ |
babel-plugin-syntax-jsx | ✔️ |
babel-plugin-syntax-logical-assignment-operators | ❌ (stage 1) |
babel-plugin-syntax-nullish-coalescing-operator | ✔️ |
babel-plugin-syntax-numeric-separator | ✔️ |
babel-plugin-syntax-object-rest-spread | ✔️ |
babel-plugin-syntax-optional-catch-binding | ✔️ |
babel-plugin-syntax-optional-chaining | ✔️ |
babel-plugin-syntax-partial-application | ❌ (stage 1) |
babel-plugin-syntax-pipeline-operator | ❌ (stage 0) |
babel-plugin-syntax-throw-expressions | ❌ (stage 2) |
babel-plugin-syntax-top-level-await | ✔️ |
babel-plugin-syntax-typescript | ✔️ |
babel-plugin-transform-arrow-functions | ✔️ |
babel-plugin-transform-async-to-generator | ✔️ |
babel-plugin-transform-block-scoped-functions | ✔️ |
babel-plugin-transform-block-scoping | ✔️ |
babel-plugin-transform-classes | ✔️ |
babel-plugin-transform-computed-properties | ✔️ |
babel-plugin-transform-destructuring | ✔️ |
babel-plugin-transform-dotall-regex | ❌ |
babel-plugin-transform-duplicate-keys | ✔️ |
babel-plugin-transform-exponentiation-operator | ✔️ |
babel-plugin-transform-flow-comments | ❌ |
babel-plugin-transform-flow-strip-types | ❌ |
babel-plugin-transform-for-of | ✔️ |
babel-plugin-transform-function-name | ✔️ |
babel-plugin-transform-instanceof | ✔️ |
babel-plugin-transform-jscript | ❌ |
babel-plugin-transform-literals | ✔️ |
babel-plugin-transform-member-expression-literals | ✔️ |
babel-plugin-transform-modules-amd | ✔️ |
babel-plugin-transform-modules-commonjs | ✔️ |
babel-plugin-transform-modules-systemjs | ❌ |
babel-plugin-transform-modules-umd | ✔️ |
babel-plugin-transform-named-capturing-groups-regex | ❌ |
babel-plugin-transform-new-target | ❌ |
babel-plugin-transform-object-assign | ❌ |
babel-plugin-transform-object-set-prototype-of-to-assign | ❌ |
babel-plugin-transform-object-super | ❌ |
babel-plugin-transform-object-rest-spread | ✔️ |
babel-plugin-transform-parameters | ✔️ |
babel-plugin-transform-property-literals | ✔️ |
babel-plugin-transform-property-mutators | ❌ |
babel-plugin-transform-proto-to-assign | ❌ |
babel-plugin-transform-react-constant-elements | ❌ |
babel-plugin-transform-react-display-name | ✔️ |
babel-plugin-transform-react-inline-elements | ❌ |
babel-plugin-transform-react-jsx | ✔️ |
babel-plugin-transform-react-jsx-compat | ❌ |
babel-plugin-transform-react-jsx-self | ✔️ |
babel-plugin-transform-react-jsx-source | ✔️ |
babel-plugin-transform-regenerator | ✔️ |
babel-plugin-transform-reserved-words | ✔️ |
babel-plugin-transform-runtime | ✔️ |
babel-plugin-transform-shorthand-properties | ✔️ |
babel-plugin-transform-spread | ✔️ |
babel-plugin-transform-sticky-regex | ✔️ |
babel-plugin-transform-strict-mode | ✔️ |
babel-plugin-transform-template-literals | ✔️ |
babel-plugin-transform-typeof-symbol | ✔️ |
babel-plugin-transform-typescript | ✔️ |
babel-plugin-transform-unicode-regex | ❌ |
babel-preset-env | ✔️ |
babel-preset-env-standalone | ❌ |
babel-preset-flow | ❌ |
babel-preset-react | ✔️ |
babel-preset-stage-0 | ❌ |
babel-preset-stage-1 | ❌ |
babel-preset-stage-2 | ❌ |
babel-preset-stage-3 | ❌ |
babel-preset-typescript | ✔️ |
babel-register | ✔️ (swc-register) |
@swc 官方插件库
@swc/cli
swc 命令行
Usage
Run the following to download pre-built binaries:
npm i -D @swc/cli @swc/core
Then, you can transpile your files:
# Transpile one file and emit to stdout
npx swc ./file.js
# Transpile one file and emit to `output.js`
npx swc ./file.js -o output.js
# Transpile and write to /output dir
npx swc ./my-dir -d output
Options
--filename (-f)
Filename to use when reading from stdin. This will be used in source maps and errors.
npx swc -f input.js
--config-file
Path to a .swcrc
file to use.
npx swc input.js --config-file .swcrc
--env-name
The name of the 'env' to use when loading configs and plugins. Defaults to the value of SWC_ENV
, or else NODE_ENV
, or else development
.
npx swc input.js --env-name='test'
--no-swcrc
Whether or not to look up .swcrc
files.
npx swc input.js --no-swcrc
--ignore
List of glob paths to not compile.
npx swc src --ignore **/*.test.js
--only
List of glob paths to only compile
Example:
npx swc src --only **/*.js
--watch (-w)
To automatically recompile files on changes, install chokidar
:
npm i -D chokidar
Then, add the -w
flag:
npx swc input.js -w
--quiet (-q)
Suppress compilation output.
npx swc input.js -q
--source-maps (-s)
Values: true|false|inline|both
npx swc input.js -s
--source-map-target
Define the file
for the source map.
npx swc input.js -s --source-map-target input.map.js
--source-file-name
Set sources[0]
on returned source map
--source-root
The root from which all sources are relative.
--out-file (-o)
Compile all input files into a single file.
npx swc input.js -o output.js
--out-dir (-d)
Compile an input directory of modules into an output directory.
npx swc src -d dist
--copy-files (-D)
When compiling a directory, copy over non-compilable files.
npx swc src --copy-files
--include-dotfiles
Include dotfiles when compiling and copying non-compilable files.
npx swc src --include-dotfiles
--config (-C)
Override a config from .swcrc
file.
npx swc src -C module.type=amd -C module.moduleId=hello
--sync
Invoke swc synchronously. Useful for debugging.
npx swc src --sync
--log-watch-compilation
Log a message when a watched file is successfully compiled.
npx swc input.js --log-watch-compilation
--extensions
Use specific extensions.
@swc/core
这些是核心 SWC API,主要对构建工具者有用。
transform
const swc = require("@swc/core");
swc
.transform("source code", {
// Some options cannot be specified in .swcrc
filename: "input.js",
sourceMaps: true,
// Input files are treated as module by default.
isModule: false,
// All options below can be configured via .swcrc
jsc: {
parser: {
syntax: "ecmascript",
},
transform: {},
},
})
.then((output) => {
output.code; // transformed code
output.map; // source map (in string)
});
transformSync
Returns { code: string, map?: string }
transformFile
Returns Promise<{ code: string, map?: string }>
transformFileSync
Returns { code: string, map?: string }
Options
This still needs to be documented. Contributions welcome!
@swc/wasm-web
该模块允许您使用 WebAssembly 在浏览器内同步转换代码。(机翻,谅解,大意就是能直接在浏览器内使用 wasm 咯)
Usage
You must first initialize the module before you can use it.
import { useEffect, useState } from "react";
import initSwc, { transformSync } from "@swc/wasm-web";
export default function App() {
const [initialized, setInitialized] = useState(false);
useEffect(() => {
async function importAndRunSwcOnMount() {
await initSwc();
setInitialized(true);
}
importAndRunSwcOnMount();
}, []);
function compile() {
if (!initialized) {
return;
}
const result = transformSync(`console.log('hello')`, {});
console.log(result);
}
return (
<div className="App">
<button onClick={compile}>Compile</button>
</div>
);
}
@swc/jest
为了让您的 Jest 测试运行得更快,您可以使用 drop-in Rust 替换 替换默认的基于 JavaScript 的运行程序 (ts-jest
) SWC。
Installation
npm i -D jest @swc/jest
Usage
Inside jest.config.js
, configure Jest to use SWC:
module.exports = {
transform: {
"^.+\\.(t|j)sx?$": ["@swc/jest"],
},
};
swc-loader
Webpack loader
Installation
npm i --save-dev @swc/core swc-loader
Usage
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules)/,
use: {
// `.swcrc` can be used to configure swc
loader: "swc-loader"
}
}
];
}
React Development
The jsc.transform.react.development
option is automatically set based on the webpack mode
.
其他推荐阅读
示例项目
- swc react 示例
- swc react typescript emotion 示例 css in js,核心就一个 d.ts 文件