SWC —— 一篇就夠

話說最近本來在倒騰 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 use React.createElement instead - with this option, you must ensure that React is in scope when using JSX.

Learn more here.

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

Learn more.

原文: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 the baseUrl.

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 in tsconfig.json files. Here is an example for how to specify the paths property for jquery.

{
  "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 to baseUrl. When setting baseUrl to another value than ".", i.e. the directory of tsconfig.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:

  1. "*": meaning the same name unchanged, so map <moduleName> => <baseUrl>/<moduleName>
  2. "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’:

  1. pattern ’*’ is matched and wildcard captures the whole module name
  2. try first substitution in the list: ’*’ -> folder1/file2
  3. result of substitution is non-relative name - combine it with baseUrl -> projectRoot/folder1/file2.ts.
  4. File exists. Done.

import ‘folder2/file3’:

  1. pattern ’*’ is matched and wildcard captures the whole module name
  2. try first substitution in the list: ’*’ -> folder2/file3
  3. result of substitution is non-relative name - combine it with baseUrl -> projectRoot/folder2/file3.ts.
  4. File does not exist, move to the second substitution
  5. second substitution ‘generated/*’ -> generated/folder2/file3
  6. result of substitution is non-relative name - combine it with baseUrl -> projectRoot/generated/folder2/file3.ts.
  7. 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 enabling minify 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 to false.
  • arrows, defaults to true.
  • booleans, defaults to true.
  • booleans_as_integers, defaults to false.
  • collapse_vars, defaults to true.
  • comparisons, defaults to true.
  • computed_props, defaults to false.
  • conditionals, defaults to false.
  • dead_code, defaults to false.
  • defaults, defaults to true.
  • directives, defaults to false.
  • drop_console, defaults to false.
  • drop_debugger, defaults to true.
  • ecma, defaults to 5.
  • evaluate, defaults to true.
  • global_defs, defaults to {}.
  • hoist_funs, defaults to false.
  • hoist_props, defaults to true.
  • hoist_vars, defaults to false.
  • ie8, Ignored.
  • if_return, defaults to true.
  • inline, defaults to ``.
  • join_vars, defaults to true.
  • keep_classnames, defaults to false.
  • keep_fargs, defaults to false.
  • keep_infinity, defaults to false.
  • loops, defaults to true.
  • negate_iife, defaults to true.
  • passes, defaults to 0, which means no limit.
  • properties, defaults to true.
  • pure_getters, defaults to ``.
  • pure_funcs, defaults to []. Type is an array of string.
  • reduce_funcs, defaults to false.
  • reduce_vars, defaults to false.
  • sequences, defaults to true.
  • side_effects, defaults to true.
  • switches, defaults to false.
  • top_retain, defaults to ``.
  • toplevel, defaults to ``.
  • typeofs, defaults to true.
  • unsafe, defaults to false.
  • unsafe_arrows, defaults to false.
  • unsafe_comps, defaults to false.
  • unsafe_Function, defaults to false.
  • unsafe_math, defaults to false.
  • unsafe_symbols, defaults to false.
  • unsafe_methods, defaults to false.
  • unsafe_proto, defaults to false.
  • unsafe_regexp, defaults to false.
  • unsafe_undefined, defaults to false.
  • unused, defaults to true.
  • 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 to false, and true is identical to {}.
  • topLevel, Defaults to false. Aliased as toplevel for compatibility with terser.
  • keepClassnames, Defaults to false. Aliased as keep_classnames for compatibility with terser.
  • keepFnames, Defaults to false.
  • keepPrivateProps, Defaults to false. Aliased as keep_private_props for compatibility with terser.
  • 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 as jsc.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 the browserslist module and any browserslist configuration files. For example, .browserslistrc or browserslist field in package.json. This can be useful if your build system isn't in the root of your project.

mode

  • string, defaults to undefined.
  • Possible values: usage, entry, undefined (this matches useBuiltIns 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 to false.
  • dynamicImport: (boolean) defaults to false.
  • loose: (boolean) defaults to false. Enable loose transformations for any plugins that allow them.
  • include: (string[]) can be a core-js module (es.math.sign) or an SWC pass (transform-spread).
  • exclude: (string[]) can be a core-js module (es.math.sign) or an SWC pass (transform-spread).
  • coreJs: (string) defaults to undefined. The version of core-js to use.
  • shippedProposals: (boolean) defaults to false.
  • forceAllTransforms: (boolean) defaults to false. 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 中將重命名爲 swcpackspack.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/spackconfig 函數包裝導出。 這是一個帶有類型註釋的標識函數。

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.

其他推薦閱讀

示例項目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章