DEV Community

Hungmi
Hungmi

Posted on • Updated on

忘了 webpacker,舊版 Rails app 升級 jsbundling-rails + Hotwire

本篇升級方式的好處

  1. 降低了現存的 Rails 4 項目升級門檻,不需要 webpacker 就能開心的使用 node packages。
  2. 若想放棄 jQuery,新頁面將不需要再導入相關依賴。
  3. 享受 Hotwire + Turbo 帶來的效率及速度優化。 希望能幫到像我一樣正在穩定開發但又想升級項目的朋友們!

先升級至 Rails 6

因為 jsbundling-railshotwire-rails 本身就限制至少 Rails 6,因此必須升級,但不需要安裝 webpacker,因此不會動到 JS & CSS 大幅降低了升級工作量,以我個人而言,從「太難了我放棄」到「兩天完成升級」🚀
Rails 的升級步驟可參考 t27duck 撰寫的 How I upgrade Ruby on Rails,其中特別注意 Step 6 Update the Default Configuration and Framework Files


本篇文章的 Sample Code 在此,建議可以看我分開 commit 的結果比較清楚✌️,也可使用 git checkout 回溯測試看看!

首先我 rails new rails_6_with_jsbundling_rails --skip-javascript 新建一個沒有任何 js 的新項目,當然,也沒裝 webpacker。

然後加入一些 JS 以及 Admin 區塊用來代表項目中已存在的功能。

接著很單純的安裝 jsbundling-rails

bundle add jsbundling-rails
rails javascript:install:esbuild
Enter fullscreen mode Exit fullscreen mode

可以看到我已經有了 package.json,表示我可以透過 yarn add 安裝所有 node packages👍。

重點

  1. 上面安裝 jsbundling-rails 的同時也裝了 foreman,因此請改用 foreman start -f Procfile.dev 開啟 Rails server + yarn build。
  2. 進到 http://localhost:3000/ 會發現舊的 JS 已經全炸了💥,而且layout 裡面載入了兩次 application.js
<head>
...
<%= javascript_include_tag 'application' %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
...
</head>
Enter fullscreen mode Exit fullscreen mode

application-thisisalonghash.js 原始碼卻是空白的,這是因為現在的 JS entry point 已經改用 app/javascript/application.js 了。

而我們需要做的就是將舊的 application.js 改名,並且微調 manifest.js 及相關的 javascript_include_tag,就可以讓新舊程式同時運作。

到這邊,我已經可以安裝 hotwire-rails

bundle add hotwire-rails
rails hotwire:install
Enter fullscreen mode Exit fullscreen mode

然後測試一下 Turbo & Stimulus 都跟舊的 JS 一起運作。

以上。


其他

雖然升級很難,但不用 webpacker 好嗎?

jsbundling-rails 也支援 webpack,而且更好
另外,未來 Rails 的主軸將會擺在 importmapjsbundling-railsDHH 也詳述了背後的原因

幹嘛要用 Hotwire?

其實繼續使用 Rails < 6 的開發方式並沒有太大的問題,例如 Stimulus 也有提供不需編譯的安裝方式,安裝之後就可以避免掉許多 SJR 替換 HTML 後需要重新初始化 JS 功能的情境。

雖然我對前端生態並不熟悉,甚至不知道將 JS 模組化的好處,但在目前的開發流程中,我發現比起 Stimulus 搭配 SJR 的組合技,使用 Hotwire 不只減少了請求數,並且維護性更佳。

幹嘛不用 CDN 安裝 hotwire 而要用 hotwire-rails gem?

雖然 Hotwire 的 Custom HTML Element <turbo-frame> 只是 plain HTML,但不使用 gem 的話,Rails controller 無法 respond_to format.turbo_stream,甚至在 *.turbo_stream.erb 的使用也會受限。

為何不用 importmap-rails?

其實我有安裝過 importmap-rails 了,也不難使用,但因為要等 Rails 7 才能使用 ActiveStorage/ActionText/ActionCable ,而我的項目暫時無法升級,所以只好放棄。
等未來 Rails 7 正式釋出時,我會考慮升級並轉換到 importmap-rails。

Discussion (0)