發現 Rails 的前端打包(build)工具已經到了眼花繚亂的地步,文件也沒寫如何搭配,老專案又該何去何從? 我做了一個排列組合分析看看。
會有這麼多情況,主要是因為
- Webpacker 被 Rails 官方 deprecated 了,這個與 webpack 深度綁一起的 gem 可能因為維護成本太高,Rails 官方不再維護了,死在 v6.0.0.rc.6。Webpacker 版號大 webpack 一號,webpacker v6 是搭配 webpack v5。webpacker v5 是搭配 webpack v4…
- sassc-rails 採用的 LibSass 核心被 Sass 官方 deprecated 了,官方改用 Dart 來實作。我不是 Sass 專長,不了解升級 Dart 版 SaSS 是否要緊,感覺可以拖一拖等有需要升級再處理。
DHH 為了想要避免初學者安裝和了解 Node.js 世界,所以預設提供的是不需要額外裝 Node.js 的 importmap 方案,以及另出一個 dartsass-rails gem 來換成 Dart Sass。
但如果真的要上線,還是得換掉 importmap 改擁抱 Node.js 世界的 jsbundling 方案。
CSS 部分 | Sass 部分 | JS 部分 | 要求另外裝Node.js | 短評 |
Sprockets | sassc-rails | Sprockets | no | 傳統 Rails 作法,無法處理 Vue.js/React 編譯需要 |
Sprockets | sassc-rails | Webpacker | yes | Rails 6 時代 DHH 建議的方案: css/image 留在 Sprockets,js 改用 webpack。 |
Webpacker | 同左 | 同左 | yes | 一度很多人建議把 Sprockets 都拆了換成 Webpacker… 現在又要逃難了 |
Sprockets | sassc-rails | importmap | no | DHH 給的新 Rails 7 預設方案 |
Sprockets | sassc-rails | jsbundling | yes | 我目前的推薦方案 |
Sprockets | sassc-rails + sass-embedded | Sprockets | no | 竟然有人 Hack sassc-ruby 改核心用 dart-sass ,看起來可以無痛升級喔 |
Sprockets | sassc-rails + sass-embedded | jsbundling | yes | 同上類似,如果需要JS編譯 |
Sprockets | dartsass-rails | importmap | no | DHH 給的升級 Dart Sass 過渡方案 |
Sprockets | dartsass-rails | jsbundling | yes | 同上類似,如果需要JS編譯 |
Sprockets | cssbundling | jsbundling | yes | DHH 發現這種組合時,可以把 Sprockets 換成精簡後的 Propshaft |
Propshaft | dartsass-rails | jsbundling | yes | 應該沒人這樣用,dartsass-rails gem 想解決是 Sprockets 搭配 Dart Sass 的場景 |
Propshaft | cssbundling | jsbundling | yes | 這是 DHH 給的 Rails 前端終極方案: 都外包給 Node.js 編譯打包,最後給 Propshaft 整合進 Rails 即可 |
Propshaft | jsbundling | jsbundling | yes | 不用 cssbundling,而是透過 jsbundling 的 bundle 工具來處理 css,例如 esbuild 的 sass plugin (感謝 Jerry Lee 分享) |
Vite Ruby | 同左 | 同左 | yes | 完全不用 Rails 給的前端方案,全部改用 Vite 處理 |
以下再個別說明一下
- Sprockets 是 Rails 歷史最久的打包編譯 CSS/JS 工具,而且最近還有在釋出更新。不過在 Node.js 新世界後,其編譯功能追不上需求了,無法處理 React 和 Vue.js 需要的編譯任務。
- sassc-rails gem (等同於 sass-rails gem 兩者一樣),是搭配 Sprockets 用的,核心是已被 deprecated 的 LibSass
- dartsass-rails gem,也是搭配 Sprockets 用的,核心換成 Dart Sass,但根據文件有 Troubleshooting,升級會有一些麻煩要處理
- sass-embedded,竟然有人 Hack sassc-ruby gem,把裡面的 LibSass 換成 Dart 版本…. 看起來完全無痛升級,比用 dartsass-rails 還簡單
- Importmap 是 Rails 直接利用瀏覽器的 JavaScript modules 功能,因此就不需要處理 JS 編譯了。不過因為瀏覽器支援還不好關係,應該還不能真的拿來上 Production 使用,也查到 ES Module Shims polyfill 可以試試看。
- cssbundling-rails 和 jsbundling-rails 都是把編譯打包任務,全都交給 Node.js 世界處理,最後丟出一個 build 好的檔案給 Asset Pipeline (Sprockets或Propshaft) 整合進 Rails。
- Propshaft 是個陽春精簡版的 Sprockets,沒有編譯和打包 css/js 的功能,只剩下最基本和 Rails 整合的任務。因為編譯和打包都透過 cssbundling-rails 和 jsbundling-rails 處理完了。
我的想法:
- 現階段 Sprockets 繼續用,有用 Vue.js/React 就再搭配 jsbundling-rails + esbuild 處理
- 之前的 Webpacker code 得拆除,這死路了。得改成用 jsbundling-rails + esbuild 處理
- 若有需要升級 Dart Sass,我會嘗試用 sass-embedded 看看,不行再試 dartsass-rails gem。真不行有需要再全面換 cssbundling-rails 以及 Sprockets 可換成 Propshaft (以上遷移成本由小到大)
- Vite Ruby 蠻有趣的,Vue.js 社群出的 Vite 工具很厲害。但這也等於都不用 Rails 提供的前端方案了,也不清楚 Vite Ruby 是否走的長遠。這可能比較適合重度前端開發,有專屬 F2E 的 Rails 團隊使用。