ボクココ

サービス開発を成功させるまでの歩み

Rails 6 における Webpacker デフォルト動作

ども、@kimihom です。

f:id:cevid_cpp:20200205165243j:plain

Rails 6 が公開されてしばらく経つ。私としては Rails 6 の中でもとりわけ Action Text でクールなテキストエリアを実現したいと思っていので、Rails 6 をゼロから学び始めている。

でも今回は Action Text とは全然関係なく、Rails 6 でのアセット管理について調べたことを残しておく。

アセットの管理

今までの Rails のアセットの管理といえば、そう Asset Pipeline だ。これで JavaScript, CSS, Font など全てを一元管理してくれていた。Rails 6 からは、デフォルトで Webpacker が Gemfile に入るようになった。Gemfile に以下が追記されている。

# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'

ここにあるコメントが大事だ。Transpile app-like JavaScript。現時点ではデフォルトの Rails 6 で作ったアプリでは JavaScript の管理 をするために Webpacker が搭載されている。つまり、CSS や Font などは引き続き Asset Pipeline を使い続けるのが、Rails 6 の利用想定である。app/views/layout/application.html.erbstylesheet_link_tag を読んでいることが Asset Pipeline を使っている証拠である。

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

Webpacker の Github にある Readme を始めとした Rails 6 でのフロントエンド の各記事を読むと、Webpacker 側で CSS や Font なども全て統括して管理する方法が掲載されていることが多い。Rails 6 の View に定義されている stylesheet_link_tag を、stylesheet_pack_tag に書き換える方法である。そして、CSS も app/javascript フォルダの中に CSS や画像も全て 突っ込むというなんとも謎なディレクトリ構造が掲載されている。

そもそも、 Rails 側でアセット管理を全部統一するってなら、最初から stylesheet_pack_tag になっているはずだ。そうじゃないのは、必ず何か理由がある。そう思って調べてみた。

Asset Pipeline の基盤となる Gem は、sprockets だ。Gemfile.lock を見てみると・・・

    sassc-rails (2.1.2)
      railties (>= 4.0.0)
      sassc (>= 2.0)
      sprockets (> 3.0)
      sprockets-rails
      tilt

これだ。sassc-rails が sprockets を必要としている。てことで Webpacker で全てのアセットを管理するのではなく、sassc-rails でスタイルシートを管理することが、Rails 6 の標準となっている可能性が高い。

Webpacker で JavaScript を書く

さて、JavaScript の書き方は Webpacker によってだいぶ変わってくる。初歩的な内容にはなるけど、Asset Pipeline と比較した Webpacker の書き方を記してみる。

まず、JavaScript ファイルの全体を管理するのが app/javascript/packs/application.js だ。

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

ここで Rails-ujs、 Turbolinks、 ActiveStorage、 Action Cable の各 JavaScript ファイルが読み込まれている。では自分で新しく作る JavaScript はどう書いていけばいいのだろう?Rails 6 で rails generate controller home を実行しても、JavaScript ファイルは自動で生成されなくなっている。

そもそも、この require はなにものかを理解する必要がある。これは JavaScript の requireimport であり、 Rails 側の何かのメソッドとかではない。外部のファイルを読み込むための記述だと思っておけばいいだろう。違いについて下記コードとして記す。

// app/javascript/my-import.js
export default  class MyImport { 
}

//  app/javascript/my-require.js
class MyRequire {
}
module.exports = MyRequire

// main.js
import MyImport from "my-import"
const MyRequire = require('my-require')

さて、これらのファイルを app/javascripts 側に書き、 app/javascript/packs/application.js に追記すれば、晴れて自分の書いた JavaScript を動かすことができる。

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require('my-require')

終わりに

今回は Rails 6 における Webpacker と、 JavaScript の書き方について簡単ではあるが記した。今回の内容はあくまで Rails のレールの話なので、Rails のレールから外れて Webpacker で CSS を含めて全部 管理したり、そもそも使わないという選択ももちろん可能だ。

引き続きRails 6 の扱い方について調査を続けていく。