Rspack 筆記-體驗超快速的前端打包工具

Eason Lin
11 min readMay 22, 2023

--

大家好,這篇文我們來試用一下 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.jsmain.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,仍須使用 sasssass-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 僅能打包模板和邏輯,樣式的部分 scopedlang 屬性皆無法作用。不過,官方也很清楚地說明了 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 打包結果:

Rspack: 28ms
Webpack: 438ms

打包時間整整差了 15 倍之多。

一個引入很大量 SCSS 的 JS 檔案

我從以前的舊專案中挖出一個將近 1MB 的 .scss 檔案進行實驗:

import "./sass/style.vue.scss"

接著分別使用 Rspack 和 Webpack 進行打包,圖一、二分別為 Rspack 和 Webpack 打包結果:

Rspack: 8516ms
Webpack: 10125ms

在打包極大量單一 CSS 檔案的狀態下,兩者的執行速度就較為接近。

一個引入很大量 JS 的 JS 檔案

一樣從舊專案挖出了數個小模組,總容量約 150KB 的幾隻 JS 檔案,統一於 ./src/index.js 引入並進行打包:

Rspack: 64ms
Webpack: 1780ms

數個引入很大量 JS 的 JS 檔案

我把原本的 ./src/index.js 複製了十份並打包十隻檔案,執行結果如下:

Rspack: 160ms
Webpack: 3446ms

在打包大量樣式的情況下,兩者的性能相對較為接近;在打包少量或大量 JS 的情況下,Rspack 的速度都是壓倒性領先。

小結

我自己在閱讀和試用 Rspack 的感覺,它的方便性、刻意模仿 Webpack 的設定檔還有極快的打包速度,都讓我覺得它是一個潛力十足的工具。若要從 Webpack 遷移到 Rspack,官方也直接提供了說明。若不是對 Vue 的支援仍不完整,我是會試著遷移看看的。

關於 Rspack 的試用筆記就記錄到這,如果內文有任何錯誤,也歡迎不吝指出。

References:

https://www.rspack.dev/zh/guide/introduction.html

https://juejin.cn/post/6915255619926622222

--

--

Eason Lin
Eason Lin

Written by Eason Lin

Frontend Web Developer | Books

No responses yet