Webpack 遷移 Rspack 速攻實戰教程(前瞻版)
題圖:Speed Crab。
rspack 即將開源,但社區中不乏有已經落地的 case ,比如 rspack-migration-showcase 、 modern.js 等。
基於此,本文將介紹如何遷移一個近似於 CRA( create-react-app ) 的項目到 rspack 。
在閱讀本文前,我們認爲讀者已經熟練掌握了 webpack 配置,本文將略過所有前置知識。
注:由於 rspack 處於 0.0.x 版本,可能會發生較大變化,故本文可能存在過時的部分,請仔細甄別。
啓動層
啓動層分 實例實現 和 DevServer 實現,他們的區別是:
webpack
// webpack 實例
import webpack from "webpack";
webpack();
// webpack dev server
import WebpackDevServer from "webpack-dev-server";
WebpackDevServer();
rspack
// rspack 實例
import * as rspack from "@rspack/core";
rspack.rspack();
// rspack dev server
import * as rspackDevServer from "@rspack/dev-server";
rspackDevServer.RspackDevServer();
// 🔴 不支持合成導入
// import rspack from 'rspack'
// import rspackDevServer from '@rspack/dev-server'
無論是 webpack 還是 rspack ,在啓動層幾乎一致,通過 實例實現 傳入配置得到 compiler ,即可引導啓動 DevServer 或進行構建,細節略:
// 獲取 compiler
const instanceImpl = rspack.rspack; // or `webpack`
const compilerImpl = instanceImpl(webpackConfig);
// 獲取 dev server
const devServerImpl = rspackDevServer.RspackDevServer; // or `WebpackDevServer`
const devServer = devServerImpl(devServerConfig, compilerImpl);
可以看到兩者無明顯區別,需要注意的是使用 compiler 的後續 api 可能存在 rspack 未支持的情況。
配置層
配置類型
兩者配置類型獲取方式:
import type { Configuration as WebpackConfig } from "webpack";
import type { Configuration as RspConfig } from "@rspack/core";
基本一致的配置項
這裏指的是直接把 webpack 的配置原模原樣拷貝給 rspack 也可以兼容的選項,經作者嘗試,常用選項如下:
-
mode -
entry -
context -
output -
devtool -
devServer -
target -
stats -
infrastructureLogging
有區別的配置項
webpack 的複雜配置需要進行一些調整才能給予 rspack 使用。
1、resolve
rspack 的 resolve 配置項要在 webpack 的基礎上加一個 tsConfigPath ,表示當前項目 tsconfig.json 的路徑:
rspackConfig.resolve = {
...webpackConfig.resolve,
tsConfigPath: ...
}
2、module - JavaScript 資源
rspack 的每個 rule 配置必須指明他的 type ,如:
module: {
rules: [
{
test: /\.tsx$/,
// 🟢
type: "tsx",
},
];
}
這和 webpack 中的 asset type 等相似,但 rspack 不光有自己獨有的 type 類型(比如 tsx 、ts 等),也支持 asset type (見下文)。
目前常用的 type 有:
-
ts/tsx -
js/jsx -
css/css/module
請各取所需。
3、module - CSS 資源
由於 webpack 的 css 配置過於繁瑣,此處僅介紹重點:
-
無需配置
style-loader、css-loader,在rspack我們用不到。 -
postcss-loader需要替換成@rspack/postcss-loader,選項的區別是插件必須傳遞實例,如:
// 獲取 postcss options
const postcssOptions = {
plugins: [
require(require.resolve("postcss-flexbugs-fixes")),
// ...
],
};
在 `webpack` 的 `postcss-loader` 選項中,插件是可以傳遞路徑的,如僅傳遞 `require.resolve('postcss-flexbugs-fixes')` ,但傳遞實例也可以,但 `rspack` 只能傳遞實例。
-
別忘了設定
css/css/module的type給對應規則。 -
sass-loader/less-loader使用、配置方式不變。
4、module - Asset 靜態資源
和 webpack 配置方式一致,可正常使用 asset type 註明靜態資源:
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/i,
type: 'asset/resource'
}
注意 svgr 需要額外設定 type: 'tsx' ,表示以 JavaScript 方式承接,否則將得到錯誤的靜態資源,另外,由於 svgr 在內部使用 babel 轉譯組件,將花費較長時間,可 fork 後修改爲 esbuild 轉譯加速,或一律將 .svg 作爲靜態資源輸出。
5、plugins - 非內置能力
目前 rspack 對 webpack 插件 hooks api 支持較少,大部分插件無法使用,可用經典插件如下:
-
clean-webpack-plugin -
webpack-bundle-analyzer
對於 html-webpack-plugin 的平替,有兩個方式可選:
-
使用
@rspack/plugin-html替代:目的是用來支持其他需要調用HtmlWebpackPlugin的後續插件,如有些插件需要在 html 模板中進一步加工,若你有二次使用HtmlWebpackPlugin的插件,請採用此方案。 -
使用內置能力
builtins.html,詳見下文。
在遷移過程中,作者發現的不可用插件如下:
fork-ts-checker-webpack-plugin
明確了哪些經典插件可以直接使用,哪些不可以後,我們距離完整補全 webpack 插件相同的能力還差一些,這些能力已在 rspack 中內置( builtins ),通過 builtins.xxx 方式配置。
6、plugins - 內置能力
builtins.define
// rspack config
builtins: {
define: {
'process.env.SOME': JSON.stringify('value'),
// ...
}
}
該能力可以平替 DefinePlugin 插件,傳值方式一致。
builtins.copy
該能力可以平替 copy-webpack-plugin ,大部分選項與 webpack 一致,但不完整,不支持 globOptions ,這意味着無法忽略某些文件不被拷貝,從而我們無法做到將 index.html 模板文件放到靜態資源目錄。
比如我們預期拷貝 public/* 到產物目錄,但 index.html 我們無法放到 public/index.html 裏,因爲不支持配置忽略就會造成多份相同資源 emit 衝突,解決方法是 html 模板只能放到項目根目錄。
builtins.react
swc 的 react 開發時配置,如下配置即可:
builtins: {
react: {
development: isDev,
refresh: isDev,
runtime: 'automatic'
}
}
builtins.bar
相當於 webpackbar 的替代,但打印容易錯位,同時 rspack 非常快,沒有必要展示進度條,不建議配置該選項。
builtins.html
內置的 html 能力,缺點是沒有提供 HtmlWebpackPlugin 插件實例,無法和其他插件聯動,同時配置項不夠完整。
值得慶幸的是 lodash template 語法無論是 builtins.html 還是 @rspack/plugin-html 均支持,如 <%= htmlWebpackPlugin.options.title %> 。
若你需支持類似 CRA 的 %PUBLIC_URL% 變量替換,請使用 react-dev-utils/InterpolateHtmlPlugin 搭配 @rspack/plugin-html ,使用方式見 CRA eject 結果。
7、plugins - 其他
到這裏,如果嚴格和 webpack 插件相比,我們還缺少一些,比如 MiniCssExtractPlugin 、ReactRefreshWebpackPlugin 、ProvidePlugin ,這些由 rspack 內置支持,我們無需配置。
當你需要更多功能時,請優先尋找平替,他可能是一個 builtins.xxx 內置能力,或是某個選項,或是某個 @rspack/plugin-xxx 包。
8、optimization
對於 optimization.minimize 兩者一致。
對於 optimization.minimizer ,我們無需外部提供壓縮能力,已經內置。
對於 optimization.splitChunks ,目前支持的分包選項不夠全面,不支持調用函數(如 name() 、test() 等),此處推薦手動使用 webpack 拆包語法分包( () => import() );可以嘗試配置非函數選項,但是否生效未知。
9、cache
雖然 rspack 有 cache 選項,但截止本文發稿時,只能配置 true / false ,並未發現有緩存出現。
由於截止本文發稿時,rspack 暫未開源文檔未釋出,請後續自行探索。
10、其他
經作者探索,將某個 JavaScript 對象傳遞至 webpack 構建流程中,是可以通過引用的方式雙向同步數據的,但在 rspack 不可以,推測這與 Rust 不支持有關。
總結
本文介紹了 webpack 遷移至 rspack 的基本流程和相關探索,至此,已經完成了 CRA 所有基本能力的平替,代碼詳見 xn-sakina / xn 。
在作者嘗試開發過程中,熱更新仍存在丟失樣式等問題,經刷新頁面後恢復,請酌情采用(如開發時 rspack 構建時 webpack)。
關於更多 rspack 能力,請自行探索開源後的文檔的選項。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/1oa4HQFwfD7nVHxB0bcadg