大家好,很高興又見面了,我是"進階前端進階",由我帶着大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發!
進階前端進階
1.什麼是 SWC?
SWC 是一個可擴充的基于 Rust 的平台,用于下一代快速開發工具。 Next.js、Parcel 和 Deno 等工具以及 Vercel、位元組跳動、騰訊、Shopify 等公司都在使用 SWC。
在 Github 上,SWC 已經有超過 26.3k 的 star 和 1k 的 fork,每周的平均下載下傳量達到了 1983k。目前有超過 6.2k 的項目使用 SWC、項目貢獻人數也達到了 200+,增長勢頭非常迅猛。
SWC 可用于編譯和打包工作,是一個超快速的 JavaScript 編譯器。 對于編譯,SWC 讀取 JavaScript / TypeScript 檔案,并輸出所有主流浏覽器都支援的代碼。在性能上,SWC 比其他打包方案具有明顯的優勢。
在單線程上比 Babel 快 20 倍,在四核上快 70 倍。
SWC 被設計為可擴充的。 目前,支援:
- 編譯(Compilation)
- 打包(swcpack,開發中)
- 壓縮
- 使用 WebAssembly 進行轉換
- 通過 swc-loader 與 webpack 內建
- 提高 Jest 性能 (@swc/jest)
- 自定義插件
2.SWC 能做什麼
SWC 可以将 TypeScript/jsx/ECMAScript 2019 轉換為浏覽器相容的 JavaScript。
2.1 浏覽器支援配置
從 v1.1.10 開始,可以使用 browserslist 自動配置支援的浏覽器。下面是.swcrc 配置檔案内容:
{
"env": {
"targets": {
"chrome": "79"
// 支援的chrome版本
},
"mode": "entry",
"coreJs": "3.22"
}
}
2.2 打包輸出子產品配置
SWC 可以使用 ES 子產品将代碼轉換為 CommonJS 或 UMD/AMD。
{
"$schema": "http://json.schemastore.org/swcrc",
"module": {
"type": "commonjs",
// 支援commonjs、es6、amd、umd
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
2.3 壓縮配置
從 v1.2.67 開始,可以通過在 .swcrc 檔案中啟用 minify 來配置 SWC 以壓縮代碼:
{
// 壓縮代碼
"minify": true,
"jsc": {
"minify": {
"compress": {
"unused": true
},
"mangle": true
}
}
}
3.SWC 與 Babel 性能對比?
JavaScript 是單線程的, JS 線程并不适合計算密集型場景,但是 SWC 不一樣。測試結果表明:即使在單核同步基準測試中,SWC 也比 babel 快 16 到 20 倍。請注意,實際性能差距可能更大,因為 swc 在工作線程上工作,而 babel 在事件循環線程上工作。
同步基準
做一個單核工作負載的基準測試。請注意,這裡使用了 transformSync,雖然生産環境幾乎不會使用。
[transform]
swc (es3) x 616 ops/sec ±4.36% (88 runs sampled)
swc (es2015) x 677 ops/sec ±2.01% (90 runs sampled)
swc (es2016) x 1,963 ops/sec ±0.45% (93 runs sampled)
swc (es2017) x 1,971 ops/sec ±0.35% (94 runs sampled)
swc (es2018) x 2,555 ops/sec ±0.35% (93 runs sampled)
swc-optimize (es3) x 645 ops/sec ±0.40% (90 runs sampled)
babel (es5) x 34.05 ops/sec ±1.15% (58 runs sampled)
SWC 非常快。盡管 swc (es3) 比 babel (es5) 做了更多的工作,但 swc (es3) 比 babel (es5) 更快。
注意:es3、es2015、es2016、es2017、es2018、react等插件、數量都有差異,具體檢視文末資料。
真實基準
transformSync 和 transformFileSync 在生産環境中很少使用,因為它會阻塞目前線程。 await Promise.all() 經常被使用,因為它優于:
for (const promise in promises) {
await promise;
}
讓我們使用 Promise.all() 為實際的使用情況建立一個基準。
理想案例
首先建立了一個基準,它立即調用 n 個 Promise,其中 n 是實體 CPU 核心的數量。
const os = require('os');
const cpuCount = os.cpus().length;
const SOURCE = `
// See the link above
`;
const SUITES = [];
const arr = [];
for (let i = 0; i < cpuCount / 2; i++) {
arr.push(0);
}
console.info(`CPU 核: ${cpuCount}; Parallelism: ${arr.length}`);
console.info(
`Note that output of this benchmark should be multiplied by ${arr.length} as this test uses Promise.all`
);
SUITES.map((args) => {
const [name, requirePath, fn] = args;
const func = fn.bind(null, require(requirePath));
bench(name, async (done) => {
await Promise.all(arr.map((v) => func()));
done();
});
});
上面代碼在舊桌面上運作基準測試,裝置是 E3-v1275 和 24GB 記憶體。下面的輸出是從基準輸出中原樣複制的。
CPU Core: 8; Parallelism: 4
Note that output of this benchmark should be multiplied by 4 as this test uses Promise.all
[multicore]
swc (es3) x 426 ops/sec ±3.75% (73 runs sampled)
swc (es2015) x 422 ops/sec ±3.57% (74 runs sampled)
swc (es2016) x 987 ops/sec ±2.53% (75 runs sampled)
swc (es2017) x 987 ops/sec ±3.44% (75 runs sampled)
swc (es2018) x 1,221 ops/sec ±2.46% (77 runs sampled)
swc-optimize (es3) x 429 ops/sec ±1.94% (82 runs sampled)
babel (es5) x 6.82 ops/sec ±17.18% (40 runs sampled)
現在,需要将它乘以 4,因為每次疊代執行 4 次操作。
swc (es3) x 1704 ops/sec ±3.75% (73 runs sampled)
swc (es2015) x 1688 ops/sec ±3.57% (74 runs sampled)
swc (es2016) x 3948 ops/sec ±2.53% (75 runs sampled)
swc (es2017) x 3948 ops/sec ±3.44% (75 runs sampled)
swc (es2018) x 4884 ops/sec ±2.46% (77 runs sampled)
swc-optimize (es3) x 1716 ops/sec ±1.94% (82 runs sampled)
babel (es5) x 27.28 ops/sec ±17.18% (40 runs sampled)
babel (es5) 的性能有所下降,畢竟是異步。盡管如此,34.05 ops/sec => 27.28 ops/sec 比預期的要好得多。
衆多操作基準
讓我們稍微修改基準檔案,使其每次疊代建立 100 個 Promise。
CPU Core: 8; Parallelism: 100
Note that output of this benchmark should be multiplied by 100 as this test uses Promise.all
[multicore]
swc (es3) x 21.99 ops/sec ±1.83% (54 runs sampled)
swc (es2015) x 19.11 ops/sec ±3.39% (48 runs sampled)
swc (es2016) x 55.80 ops/sec ±6.97% (71 runs sampled)
swc (es2017) x 62.59 ops/sec ±2.12% (74 runs sampled)
swc (es2018) x 81.08 ops/sec ±5.22% (75 runs sampled)
swc-optimize (es3) x 18.60 ops/sec ±2.13% (50 runs sampled)
babel (es5) x 0.32 ops/sec ±19.10% (6 runs sampled)
它必須像上面那樣乘以 100。
swc (es3) x 2199 ops/sec ±1.83% (54 runs sampled)
swc (es2015) x 1911 ops/sec ±3.39% (48 runs sampled)
swc (es2016) x 5580 ops/sec ±6.97% (71 runs sampled)
swc (es2017) x 6259 ops/sec ±2.12% (74 runs sampled)
swc (es2018) x 8108 ops/sec ±5.22% (75 runs sampled)
swc-optimize (es3) x 1860 ops/sec ±2.13% (50 runs sampled)
babel (es5) x 32 ops/sec ±19.10% (6 runs sampled)
為什麼 SWC 的性能沒有大幅下降? 秘訣在于 Node.js, Node.js 内部管理一個工作線程池,SWC 運作在上面。 是以,即使一次建立 100 個 Promise,工作線程的數量也比它少得多。
基準測試結論
資料表明:swc 擴充性很好,因為它幾乎所有工作都在工作線程中完成。 從 100 個 promise 的吞吐量優于 4 個 promise 的事實,可以得出結論,Node.js 的工作線程池使用了超線程(Hyperthreading)。
swc 随着 cpu 核數量的增加而增加,Promise.all 足以進行擴充。
4.從 Babel 遷移 SWC
4.1 從@babel/core 遷移
運作如下指令:
npm i --save-dev @swc/core
// 或者
yarn add --dev @swc/core
Swc 預設啟用所有通道, 是以如果隻使用标準的 ecmascript,則可以删除 .babelrc 并将 babel.transform() 更改為 swc.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)
});
4.2 從@babel/cli 遷移
運作如下指令:
npm i --save-dev @swc/core @swc/cli
// 或者
yarn add --dev @swc/core @swc/cli
進行安裝。 @swc/cli 的 CLI api 幾乎等同于@babel/cli。 是以,如果使用的是标準 ecmascript,則隻需将 npx babel 替換為 npx swc。另請注意,swc 尚不支援自定義插件。
// 轉譯一個檔案并發送到标準輸出
npx swc ./file.js
// 轉譯一個檔案并發送到 `output.js`
npx swc ./file.js -o output.js
// 轉譯并寫入 /output 目錄
npx swc ./my-dir -d output大家好,很高興又見面了,我是"進階前端進階",由我帶着大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發!
5.本文總結
本文主要和大家介紹下SWC,文章從什麼是 SWC、SWC 能做什麼、SWC 與 Babel 性能對比、從 Babel 遷移 SWC等諸多元度展開。當然,因為篇幅有限,文章并沒有過多展開,如果有興趣,文末的參考資料提供了大量優秀文檔以供學習。
參考資料
https://swc.rs/blog/swc-1#how-fast-is-swc
https://swc.rs/blog/swc-1
https://swc.rs/docs/usage/core
https://swc.rs/docs/usage/cli
https://swc.rs/docs/configuration/minification
https://github.com/swc-project/swc
封面圖檔版權:https://morioh.com/p/069cc1dd1058