大家好,這篇文我們來試用一下 Rspack。
Rspack 是一個基於 Rust 的打包工具,可以幫助我們把前端撰寫的原始碼轉換成瀏覽器看得懂的樣子。相信讀到這裡應該也能看出,這是一個功能類似於 Webpack 的工具。那為什麼會有 Rspack 呢?
Rspack 想要解決什麼問題
Rspack 的誕生其實和 Webpack 有著很大關係。更直白地說,它是因為 Webpack 本身性能限制而出現。相較於 Webpack 和其他類似的打包工具,根據官方所述,Rspack 具有以下優勢:
- 快速的開發環境啟動速度
- 高效的生產環境程式碼產生速度
- 更加靈活的客製化設定
- 生產環境的優化能力
同樣根據官方所述,直接與 Webpack 相比,Rspack 的優勢是:
- Rspack 基於性能接近 C++ 的 Rust,相較基於 Node.js 的 Webpack 效率更高
- Node.js 雖然在 13 版後已經可以支援並行處理,相較於採用高度並行化架構的 Rust 仍有一定差距
- Rspack 已經內建了大部分的功能,Webpack 以往要加入大量 Plugins 和 Loaders,這些也都會一定程度影響效能
快速開始
JavaScript 打包
Rspack 的入門,相對於 Webpack 我覺得容易許多。我們可以在一個空資料夾中輸入:
# 建立一個 index.js
touch index.js
# 初始化 npm
npm init -y
# 安裝 rspack
npm install -D @rspack/cli
// index.js
function add(x, y) {
return x + y
}
console.log(add(1, 2))
建立 Rspack 設定檔 rspack.config.js
,它的配置跟 Webpack 非常接近:
const path = require('path');
module.exports = {
entry: {
main: './index.js',
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
接著我們調整 package.json
加入 Rspack 的打包指令:
{
"name": "rspack-starter",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "rspack serve",
"build": "rspack build"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@rspack/cli": "^0.1.10"
}
}
輸入 rspack build
進行打包:
這時候 /dist
資料夾應該會有 main.js
和 main.js.map
兩個檔案。如果我們使用 node 去執行 /dist/main.js
:
表示打包是有成功的。
我們也可以配置一個包含 index.html
的專案:
// rspack.config.js
/** @type {import('@rspack/cli').Configuration} */
const config = {
context: __dirname,
entry: {
main: "./index.js"
},
builtins: {
html: [
{
template: "./index.html"
}
],
}
};
module.exports = config;
在根目錄建立 index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
稍微調整一下 index.js
:
function add(x, y) {
return x + y
}
document.getElementById('app').textContent = add(20, 30)
打開終端機,輸入 npm run dev
:
這時如果打開 http://localhost:8080/,應該可以看到:
Rspack 會為我們啟動一個預設 PORT 為 8080,並且能渲染 index.html
內容且能依照頁面改動進行 HMR 的頁面,我們可以輸入 npm run build
把原始碼輸出到 /dist
:
TypeScript 轉譯
無須額外配置,即可進行對 TypeScript 的轉譯:
/** @type {import('@rspack/cli').Configuration} */
const config = {
context: __dirname,
entry: {
test: "./src/test.ts",
},
devtool: false,
};
module.exports = config;
於指定的 ./src/test.ts
撰寫 TypeScript:
interface User {
name: string;
id: number;
}
const user: User = {
name: "Hayes",
id: 0,
};
console.log(user);
會於 ./dist/
產生 test.js
:
!function(){var o={899:function(o,r,n){console.log({name:"Hayes",id:0})}},r={};!function n(e){var t=r[e];if(void 0!==t)return t.exports;var i=r[e]={exports:{}};return o[e](i,i.exports,n),i.exports}("899")}();
CSS 打包
不須配置任何額外插件,只需要在 rspack.config.js
進行設定:
/** @type {import('@rspack/cli').Configuration} */
const config = {
context: __dirname,
entry: {
style: "./src/style.css",
},
module: {
rules: [
{
test: /\.css$/i,
type: "css",
},
],
},
devtool: false,
};
module.exports = config;
於指定的 ./src/style.css
撰寫 CSS:
h1 {
color: red;
}
會於 ./dist/
產生 style.css
:
h1{color:red}
SCSS 打包
要打包 .scss
,仍須使用 sass
及 sass-loader
:
npm install sass sass-loader
配置會是:
/** @type {import('@rspack/cli').Configuration} */
const config = {
context: __dirname,
entry: {
style: "./src/style.scss",
},
module: {
rules: [
{
test: /\.scss$/,
use: ["sass-loader"],
type: "css",
},
],
},
devtool: false,
};
module.exports = config;
./src/style.scss
長這樣的話:
@mixin myMixin {
color: red;
font-size: 48px;
font-weight: 700;
}
h1 {
@include myMixin;
}
實際進行打包後,產出的檔案 ./dist/style.css
內容會是:
h1{color:red;font-size:48px;font-weight:700}
React
類似對 TypeScript,Rspack 對 JSX 也有內建支援。官方提供的 React 專案範例非常多,可直接參考其中一種範例。
Vue
比較可惜的是,Rspack 目前對 Vue 的支援仍不完整,我實測下來 v0.1.10
僅能打包模板和邏輯,樣式的部分 scoped
和 lang
屬性皆無法作用。不過,官方也很清楚地說明了 Vue 提供完整支持是他們的計畫。照他們一兩周一個版本的迭代速度來看,我個人認為只是時間問題。
實測效能
我根據一些場景做了一些實驗,先把我的幾個實驗情境列出:
- 一個很單純引入一個模組的 JS 檔案
- 一個引入很大量 SCSS 的 JS 檔案
- 一個引入很大量 JS 的 JS 檔案
- 數個引入很大量 JS 的 JS 檔案
一個很單純引入一個模組的 JS 檔案
我使用一個算有名的函式庫 the-answer
,將其引入並印出:
// index.js
const answer = require( 'the-answer');
console.log( 'the answer is ' + answer );
接著分別使用 Rspack 和 Webpack 進行打包,圖一、二分別為 Rspack 和 Webpack 打包結果:
打包時間整整差了 15 倍之多。
一個引入很大量 SCSS 的 JS 檔案
我從以前的舊專案中挖出一個將近 1MB 的 .scss
檔案進行實驗:
import "./sass/style.vue.scss"
接著分別使用 Rspack 和 Webpack 進行打包,圖一、二分別為 Rspack 和 Webpack 打包結果:
在打包極大量單一 CSS 檔案的狀態下,兩者的執行速度就較為接近。
一個引入很大量 JS 的 JS 檔案
一樣從舊專案挖出了數個小模組,總容量約 150KB 的幾隻 JS 檔案,統一於 ./src/index.js
引入並進行打包:
數個引入很大量 JS 的 JS 檔案
我把原本的 ./src/index.js
複製了十份並打包十隻檔案,執行結果如下:
在打包大量樣式的情況下,兩者的性能相對較為接近;在打包少量或大量 JS 的情況下,Rspack 的速度都是壓倒性領先。
小結
我自己在閱讀和試用 Rspack 的感覺,它的方便性、刻意模仿 Webpack 的設定檔還有極快的打包速度,都讓我覺得它是一個潛力十足的工具。若要從 Webpack 遷移到 Rspack,官方也直接提供了說明。若不是對 Vue 的支援仍不完整,我是會試著遷移看看的。
關於 Rspack 的試用筆記就記錄到這,如果內文有任何錯誤,也歡迎不吝指出。
References: