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