Slide 1

Slide 1 text

爆速スッキリ! Rspack 移行の成果と道のり Muddy Web #11 ~Special Edition~ 2025.03.21

Slide 2

Slide 2 text

どら WINTICKET Webチーム   @d0ra1998 今月 グランドサークル を回ってきました

Slide 3

Slide 3 text

今回話すこと WINTICKET Web を
 Webpack + Babel から Rspack + SWC に移行しました C Rspack, SWCに移行した経b C 移行のプロセB C 大変だったこc C 得られた成果

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

WINTICKET Web の技術構成 SSRを行うIsomorphic Application Babelに依存する周辺ライブラリ

Slide 6

Slide 6 text

WINTICKET Web の規模感 50万行 TS/TSX 7,000 ファイル 50秒 ローカル起動

Slide 7

Slide 7 text

Rspack とは R ByteDance 社が開発する Rust 製の JS バンドy R Webpack 5 と互換性があW 2 Config / Plugin / Loader が基本そのまま動 R 2024/8 に v1.0 がリリース

Slide 8

Slide 8 text

Webpack を剥がすモチベーション  速度アップによる開発生産性向t € 特にイテレーションを繰り返すローカル開発を改善したf  Babel, Webpack の設定を整理するタイミンW € レガシーブラウザ向けの別ビルド機% € 更新されていない browserslist

Slide 9

Slide 9 text

一旦移行してみる 基本的には config, CLI の webpack を rspack に書き換えるだけ webpack.config.js  →  rspack.config.js https://rspack.dev/guide/migration/webpack#updating-packagejson

Slide 10

Slide 10 text

一旦移行してみる 一部プラグインを Rspack 提供のものに置き換え https://rspack.dev/guide/migration/webpack#copy-webpack-plugin

Slide 11

Slide 11 text

一旦移行してみる cache フィールドは Object に対応しておらず Boolean のみ 1 2 3 4 5 6 7 8 9 10 { cache { type , } cache , } // Webpack // ... // Rspack - : - : - - + : 'filesystem' true

Slide 12

Slide 12 text

一旦移行してみる optimization.splitChunks.cacheGroups.{cacheGroup}.name の引数の型に
 若干互換性がなかったので修正 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { optimization { splitChunks { cacheGroups { lib { (module, _chunks, cacheGroupKey) { hash crypto. ( ); hash. (module. ({ context __dirname })); hash. (path. (__dirname, module.resource)); ${cacheGroupKey} ${hash. ( ). ( , )} ; }, } } } } } : : : : = - : + name createHash update libIdent update relative digest substring const return 'sha1' ` - 'hex' ` // Webpack // Rspack 0 8

Slide 13

Slide 13 text

ローカルサーバーの起動速度を比較 41秒 Rspack 50秒 Webpack

Slide 14

Slide 14 text

トランスパイラをBabel → SWCに置き換え

Slide 15

Slide 15 text

SWC とは b Rust 製の JS / TS コンパイラ・バンドA b Next.js Compiler でも使われていR b プラグイン機構があり、
 一部 Babel プラグインの代替実装が存在

Slide 16

Slide 16 text

ローカルサーバーの起動速度を比較 20秒 Rspack + SWC 41秒 Rspack + Babel

Slide 17

Slide 17 text

ローカルサーバーの起動速度を比較 50秒 36秒 41秒 20秒 Rspack + SWC Webpack + SWC ※参考 Webpack + Babel Rspack + Babel

Slide 18

Slide 18 text

当初計画していた移行ステップ 1. Webpack + Babel → Webpack + SWC 2. ローカル開発のみ、Rspack + SWC移行 3. 本番含め全てRspack + SWC移行

Slide 19

Slide 19 text

1. Webpack + Babel → Webpack + SWC バンドラは変えず、Rspack移行に向けて以下を行っ„ a トランスパイラを Babel → SWC d a サポート対象に合わせて、設定の削除・調Y a レガシーブラウザ向けの別ビルド機構を削4 a output.environment で一部記法を有効に

Slide 20

Slide 20 text

1. Webpack + Babel → Webpack + SWC バンドラは変えず、Rspack移行に向けて以下を行っ„ a トランスパイラを Babel → SWC d a サポート対象に合わせて、設定の削除・調Y a レガシーブラウザ向けの別ビルド機構を削4 a output.environment で一部記法を有効に うまくいかず…

Slide 21

Slide 21 text

1. Webpack + Babel → Webpack + SWC † `Cannot access uninitialized variable.` エラーが一部ページ遷移時に起きH † iOS 15系の一部マイナーバージョンで発a † Safariの開発者ツールを開いてると起きな6 † デバッグが困難で原因特定できず、なぜかRspackに移行すると発生しな6 † このステップを飛ばしてRspackへ移行することに

Slide 22

Slide 22 text

実際の移行ステップ 1. Webpack + Babel → Webpack + SWC (失敗) 2. ローカル開発のみ、Rspack + SWC移行 3. 本番含め全てRspack + SWC移行

Slide 23

Slide 23 text

2. ローカル開発のみ、Rspack + SWC移行 x 本番適用前から高速化の恩恵を得られるように先んじて移H x 本番(Webpack)との一時的な差分は許… x QCに加えて、普段の開発で問題がないことを確認

Slide 24

Slide 24 text

3. 本番含め全てRspack + SWC移行

Slide 25

Slide 25 text

大変だったこと W Babel → SWC への置き換C W SWC プラグインの @swc/core とのバージョン相' W SWC 移行に伴う @visx/text のデグ5 W Storybook 向けに Rsbuild の設定を作成

Slide 26

Slide 26 text

Babel → SWCへの置き換え 14個のpluginを1つずつ確認 B plugin-proposal-* B B → SWC の env で代v plugin-react-remove-properties は削‚ B data-testid は消していないサービスも多t B 該当箇所も少なく、値も露出して問題なかったため削‚ 周辺ライブラリのプラグインはSWC実装が存f B @loadable/babel-plugin → @swc/plugin-loadable-componenty B babel-plugin-styled-components → @swc/plugin-styled-components

Slide 27

Slide 27 text

# SWC の WASM プラグインには後方互換性がなb # SWC 本体とプラグインで swc_core のバージョンを合わせてあげる必要があ # SWC Plugins で適切なバージョン範囲がわかる SWC プラグインの @swc/core とのバージョン相性

Slide 28

Slide 28 text

SWC 移行に伴う @visx/text のデグレ VRT で @visx/text の使用箇所に表示崩れを発見

Slide 29

Slide 29 text

SWC 移行に伴う @visx/text のデグレ VRT で @visx/text の使用箇所に表示崩れを発見

Slide 30

Slide 30 text

SWC 移行に伴う @visx/text のデグレ dy属性にCSS calc()が入ってエラーになっている…? Babel SWC

Slide 31

Slide 31 text

SWC 移行に伴う @visx/text のデグレ @visx/text 調査 該当箇所では reduce-css-calc が呼ばれ、SWC移行までは具体の数値に置き換えられていた ※ visx/packages/visx-text/src/hooks/useText.ts · airbnb/visx https://github.com/airbnb/visx/blob/7c70f714992232a3416f990af9a064ce57b2d5f3/packages/visx-text/src/hooks/useText.ts#L85-L94

Slide 32

Slide 32 text

SWC 移行に伴う @visx/text のデグレ reduce-css-calc 調査 reduce-css-calc の内部では例外が起こると元の値を静かに返していた ※ reduce-css-calc/index.js · MoOx/reduce-css-calc https://github.com/MoOx/reduce-css-calc/blob/077b6d74d3807744c2854f7ba3a60626dcfdb504/index.js#L78-L83

Slide 33

Slide 33 text

SWC 移行に伴う @visx/text のデグレ math-expression-evaluator 調査 math-expression-evaluator 内部では `i is not defined` というエラーが発生していた ※ [math-expression-evaluator/src/lexer.ts · bugwheels94/math-expression-evaluator https://github.com/bugwheels94/math-expression-evaluator/blob/0f2531b1334d1bcb65ebaadb6476b30b01814ef2/src/lexer.js#L162

Slide 34

Slide 34 text

SWC 移行に伴う @visx/text のデグレ math-expression-evaluator 調査 変数iの宣言が漏れており修正済み。Babel + Terser 時代は運よく動いてた模様。 https://github.com/bugwheels94/math-expression-evaluator/commit/91b9fe61d54ea260f95f619dbd61580b8c840c72

Slide 35

Slide 35 text

SWC 移行に伴う @visx/text のデグレ math-expression-evaluator を overrides で上書きして解決 ※補足 reduce-css-calc v2 では math-expression-evaluator への依存は無くなっているため、reduce-css-calc のバージョンを上書きする選択肢もあったが、 @visx/text は reduce-css-calc ^1.3.0 を peerDeps としているため、避けている

Slide 36

Slide 36 text

Storybook 向けに Rsbuild の設定を作成 W Storybook builder に Rspack はなT W 代わりに Rsbuild の builder が用意されてい@ W https://rspack.dev/guide/migration/storyboop W Rsbuild ではなく Rspack を使わせてほしいという要望は上がってい@ W https://github.com/rspack-contrib/storybook-rsbuild/issues/92

Slide 37

Slide 37 text

Rsbuildとは @ Rsbuild は Rspack をラップしたビルドツー6 @ 設定のインターフェースは Vite 風味 https://rsbuild.dev/guide/start/index

Slide 38

Slide 38 text

Storybook 向けに Rsbuild の設定を作成 c @rsbuild/plugin-react をベースに作E c tools.rspack にRspackの設定をそのまま書けるので、適宜持ってくる 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 export default const return new ({ plugins [ (), ()], source { define { . (process.env. ), }, }, tools { () { swcConfig . (fs. (path. ( , ), )); swcConfig; }, rspack { plugins [ rspack. ({ }), ], }, }, }); defineConfig pluginReact pluginNodePolyfill stringify swc parse readFileSync join CopyRspackPlugin : : : : : : => = : : 'process.env.FOO' JSON FOO JSON APP_ROOT '.swcrc' 'utf-8' // ここに Rspack の設定が書ける // ...

Slide 39

Slide 39 text

移行してよかったこと 16秒 Rspack 79秒 Webpack 20秒 Rspack 50秒 Webpack 本番ビルド ローカルサーバー起動

Slide 40

Slide 40 text

移行してよかったこと E エコシステム進化の恩恵を受けられ E Rspack, SWC の継続的な高速化など

Slide 41

Slide 41 text

まとめ h Rspack は Webpack から手軽に移行できE h 大変だったポイントはほとんど Babel → SWC 移I h 高速化するにはトランスパイラなど周辺の変更も必1 h 予期せぬデグレが伴うので、VRT や E2E, 手動 QC はとても大事

Slide 42

Slide 42 text

ライセンス 本スライド中のロゴは下記ライセンスに基づいて使用しています MIT Licens( e Babel - Sebastian McKenzi( e loadable-components - Greg BergÉ e Storybook - Storybooks CC-BY-4.Æ e React CC BY-NC-SA 4.Æ e Rspack