個人プロジェクトを最新の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を使いません。

手順はほぼこれです。

遅まきながらRails5の頃に作ったプロジェクトをyarn化する(webpacker無し) - PIYO - Tech & Life -
Rails5の頃に作ったプロジェクトで、JS系のアセットの管理にはRails Assetsを使っている、Rails 5.1のプロジェクトが手元に

できるだけ全部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.jspacks/application.js.erbとリネームしました。これはRails管理のJSをimportするためです。

gemが持ってるJSをwebpackerで読み込むには - PIYO - Tech & Life -
手持ちのレガシー目なRails案件をいい加減Webpackerに直す活動を始めていまして、まずは仕事以外のプロジェクトからやってます。 JS用

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_tagjavascript_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_tagstylesheet_pack_tagに変更すればOKのはずです。

ちなみにここでハマったのはsassファイルに凡ミスがあってコンパイルエラーになったときに、エラーメッセージにはcssファイルがないよ、としか表示されなくて原因がわからなくて困ったというやつです。

public/packs配下にもapplication.cssが書き出されていなくて設定ミスかな?なんて思っていたんですが、webpack-dev-serverを動かしてみたらsass側にエラーがあったというオチでした。

終わり

ここまででひとまずsprocketsを使わないようにできたのではないかと思います。本当はちゃんと新しいJSでかけるようにしたり、coffeeスクリプトをやめたり、ESLintをかけられるようにしたりとモダンにしていきたいところ。