個人プロジェクトを最新のRailsアップグレードして、Webpackerを使えるところまでやりました。自分への覚書の意味もこめて。
Railsを5.2までアップグレードする
- Rails以外のgemをupdateしておく
- Rails 5.1にアップグレード
bin/rails app:update
する- 差分を調整する
- new_framework_defaultsあたりも注意する
- 軽く動かして警告などに対応する
- Rails 5.2にアップグレード
- 手順は5.1と一緒
まずはyarnを使う
gemやrails-assetsで追加していたJSライブラリやCSSなどをyarnで管理するように変更します。この時点ではwebpackerを使いません。
手順はほぼこれです。
できるだけ全部yarn側に持っていくことをおすすめします。jqueryとかbootstrapとかもです。webpacker化しちゃってから対応すると面倒だった記憶があります(一度やった)。
また、この時点でメンテされていないライブラリがあったら実装を置き換えておくのがいいかもしれません。今回対応したプロジェクトではcolorpicker系のライブラリを置き換えました。
Railsのヘルパー系とJSを一緒に提供するようなgemはyarn管理に持っていけないので、それはwebpacker管理に変更したのちに個別に対応しました(後述)。
webpackerのインストール
いよいよwebpackerを入れますが、ここではあまり欲張らず既存のcoffeeスクリプトをそのまま活かす形にしました。JSへ変換するスクリプトなんかを使うとなかなか大変そうだということがわかったので(これも一度やりました)。
Gemfileにgem 'webpacker'
を追記して、
% bundle install
% rails webpacker:install
% rails webpacker:install:erb # erbとして読むため
% rails webpacker:install:coffee # coffeeを読めるようにするため
JSを移動
app/assets/javascripts
にあったcoffeeスクリプトのファイルを新しくできたapp/javascript/packs/
以下のフォルダへ移動します。packs
配下に直接置くとエントリポイントになっちゃうので一つ階層を置くと良さそうです。pages
などとしてその下に置きます。
packs/application.js
はpacks/application.js.erb
とリネームしました。これはRails管理のJSをimportするためです。
application.js.erb
は例えば以下のようになるかと思います。
// packs/application.js.erb
import jQuery from 'jquery/dist/jquery';
window.jQuery = jQuery;
window.$ = jQuery;
import 'jquery-ujs/src/rails.js'
import 'bootstrap-sass/assets/javascripts/bootstrap.js'
import "<%= File.join(Gem.loaded_specs['cocoon'].full_gem_path, 'app', 'assets', 'javascripts', 'cocoon.js') %>"
import './pages/items.js.coffee'
import './pages/map.js.coffee'
従来のapplication.js
で書いていたようなrequire jquery
のような部分をimportに変えつつ、先程移動したcoffeeスクリプトも相対パス指定で直接書いていきます。globを使うような方法もありそうでしたが、今回は数が少なかったので調べませんでした。
あとはView側のjavascript_include_tag
をjavascript_pack_tag
と変更すればOK。ここで動作確認をしておくと良いです。
ちなみにjqueryは他のライブラリからグローバルに参照されることが多かったり、自身のView側のJSのコードでもそのように書いていることがあり得るので最初の3行のようにして参照できるようにしています。
CSSもwebpacker
packs/application.js.erb
でsassをimportするとそれもコンパイルされ、application.cssとして参照されるようになります。なので、CSSもこちらに移動しましょう。手順はほぼ一緒ですが、importの書き方に工夫が要ります。
まずapplication.jsに以下を追記
import '../styles/application.sass'
packsと同じ階層にstyles
ディレクトリを作ってそこにapplication.sass
というファイルを配置。
中身はこんな感じです。
@import "~bootstrap-datepicker/dist/css/bootstrap-datepicker3"
@import "~toastr/toastr.scss"
@import 'common'
yarn管理のライブラリには~
をつける必要があります。これをつけるとnode_modulesからのパスになるようです。
あとは、stylesheet_link_tag
をstylesheet_pack_tag
に変更すればOKのはずです。
ちなみにここでハマったのはsass
ファイルに凡ミスがあってコンパイルエラーになったときに、エラーメッセージにはcssファイルがないよ、としか表示されなくて原因がわからなくて困ったというやつです。
public/packs
配下にもapplication.css
が書き出されていなくて設定ミスかな?なんて思っていたんですが、webpack-dev-server
を動かしてみたらsass
側にエラーがあったというオチでした。
終わり
ここまででひとまずsprocketsを使わないようにできたのではないかと思います。本当はちゃんと新しいJSでかけるようにしたり、coffeeスクリプトをやめたり、ESLintをかけられるようにしたりとモダンにしていきたいところ。