Rails6にjQueryとBootstrapを導入する手順
August 9, 2020
かなり手間取ったので振り返り用にメモ。同じように導入が上手くいかずに苦しんでいる方への手助けになればと。
この記事でやろうとしていること:Rails6 に Yarn で(Webpacker 用に)jQuery と Bootstrap をインストールして、アプリ上で使えるようにする。
なお私は下記の原因で苦戦した。
- 苦戦の原因その1
- Rails6 から、JavaScript の標準バンドラーは Webpacker になったこと
- 苦戦の原因その2
- Turbolinks の存在
苦戦する中で色々なウェブサイトを見て調べた。ほとんどのウェブサイトでは、なぜそのような作業をするのかを説明がなくいまいち釈然としなかったが、最終的には下記の記事が最も参考になった。この記事も下記を参考にして作成している(特に後編の方)。
Rails 6: Webpacker+Yarn+Sprockets を十分理解して JavaScript を書く: 前編(翻訳)
Rails 6: Webpacker+Yarn+Sprockets を十分理解して JavaScript を書く: 後編(翻訳)
ただし、必ずしも上記の記事とやりたいことが一致しているわけではないため、上記と本記事で相違点が出てくる部分もあることに注意をば。
また、Rails5 までは Sprockets というバンドラーを利用して、css・js・画像をプリコンパイルしていたのだが、Rails6 のデフォルトでは、css と画像は引き続き Sprockets で、js だけは Webpacker で扱うというように運用が変わっている。この運用を不思議に思ったが、下記の記事が良い参考になったので、あわせてリンクを残しておく。
なぜ Rails 6 には Webpacker と Sprockets の両方が含まれているのでしょうか?
では、以下、導入手順を書いていく。
1 − 1.Yarn で jQuery と Bootstrap をインストールする #
ここは特に問題なく作業できると思う。
ターミナルからプロジェクトのディレクトリ上で、以下を入力し実行。
yarn add bootstrap jquery popper.js
Bootstrap と jquery と popper.js をインストールしている。
本記事作成時点で、Bootstrap の最新版はバージョン4だが、これを利用するためには jQuery と popper.js が必要(バージョン4から、jQuery に加えて popper.js も必要になった)。
1 − 2.js をインクルードする #
対象のファイルに記載を追加する。
→ app/javascript/packs/application.js
require('jquery'); // jQueryを追加
require('bootstrap'); // Bootstrapを追加
なお、冒頭で紹介した記事の中で説明されているが、bootstrap の方の記述があれば jquery の記述は不要(同じ理由で、popper.js の記述も不要)。私は、 jQuery を使っていることを意識したいため、あえて記述を残している。
また、require(‘bootstrap/dist/js/bootstrap.min’)ではなく、単に bootstrap と書くだけで大丈夫である理由も、先の記事に説明がある。
1 − 3.css をインクルードする #
対象のファイルに記載を追加する。
→ app/assets/stylesheets/application.css
*= require bootstrap/dist/css/bootstrap.min.css
なお、bootstrap は一番最初にインクルードさせるべきである。bootstrap にはリセット CSS(bootstrap4 では、Reboot.css というもの)が含まれているため、後からこれを読み込ませてしまうと、他の CSS で設定したものが上書きされて消えてしまうため。
また、リンク先の記事では、CSS を SCSS に変更して運用しているが、私の場合は Rails のデフォルトのまま CSS で運用しているため、ファイル内に記述する形式が異なっているので注意。
1 − 4.全ての pack で jQuery を使えるようにする #
対象のファイルに記載を追加する。
→ config/webpack/environment.js
const { environment } = require('@rails/webpacker');
// ここから
const webpack = require('webpack');
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
})
);
// ここまで
module.exports = environment;
これも詳細理由はリンク先記事のなかに記載がある。
また、jQuery は下記2つの書き方ができる(特に WordPress では後者が使われているらしい)。
$('h1').on('click', function () {
$(this).css('color', 'blue');
});
jQuery('h1').on('click', function () {
jQuery(this).css('color', 'blue');
});
そのため、リンク先では「$: ‘jquery’,」だけを書いているが、「jQuery: ‘jquery’」も加えておいた方が安心。
ここまでで導入はひとまず終わり #
あとは使えるようになったことを確認していく。
2 − 1.テスト用の js ファイルを作る #
ファイルを作成し、中身を記載。
→ app/javascript/packs/test.js
$(document).on('turbolinks:load', function () {
$('p').on('click', function () {
$(this).css('color', 'blue');
});
});
p タグをクリックすると青色になるというもの。お好みで h1 タグにしても良いし、赤色にしても良いし。ご自由に。
2 − 2.テスト用の js ファイルをインクルードする #
対象のファイルに記載を追加する。
→ app/javascript/packs/application.js
require('./test.js'); // テスト用
これで先の js(jQuery)が全てのビューで適用される。
なお全てのビューでなく、特定のビューのみに適用したいという場合は、上記は実施せず、ビュー内に以下を記載する。
→ app/views/tests/test.html.erb(tests 配下の test に適用したいと仮定して)
<%= javascript_pack_tag 'test' %>
2 − 3.ビューにテスト用のコードを追加する #
対象のファイルに記載を追加する。
→ app/views/tests/test.html.erb(tests 配下の test に適用したいと仮定して)
<p>test</p>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
前者は先ほど作った js(jQuery)ファイルが適用されているかの確認用。後者は Bootstrap のコンポーネントである。
#Dismissing Alerts - Bootstrap 4.3 - 日本語リファレンス
Bootstrap のコンポーネントには、js を必要とするものとしないものがあるが、このコードは js を必要とするものである。そのため、このコンポーネントが使えていれば Bootstrap の CSS と js どちらもちゃんと適用できていることが確認できる。
2 − 4.確認する #
ここまでで準備作業は終わり。あとは確認するだけ。
ビューを開いて、p タグをクリックし、jQuery の適用を確認する。Bootstrap のコンポーネントが、リファレンスのデモ通りに表示・動作(× を押すと消えるか)するか確認する。
無事に動けば作業終了。テスト用の設定や js ファイルは消すなりお好きに。
最後に、私が苦戦した部分の整理 #
冒頭に書いた通り、私は下記で苦戦した。
- 苦戦の原因その1
- Rails6 から、JavaScript の標準バンドラーは Webpacker になったこと
- 苦戦の原因その2
- Turbolinks の存在
1点目については、Rails6 がまだ比較的新しいことから、作業手順をまとめてくれているウェブサイトがそれほど多く見つからないことが原因である。探せばそれなりに見つかるものの、サイトによって書いてある内容がマチマチだったため、自分なりに初心者の観点から整理しようと思ったのがこの記事の1つのきっかけ。
2点目は Turbolinks の存在である。「2 − 1.テスト用の js ファイルを作る」に関してだが、私は最初、以下のコードをファイルに記載して確認しようとしていた。
$(function () {
$('p').on('click', function () {
$(this).css('color', 'blue');
});
});
Turbolinks について解説してくれているウェブサイトは多数あるため、ここで説明はしないが、Turbolinks が原因で起きる有名な問題として 「$(function()や、$(document).ready()や、$(window).load()
が発火しない」というものがあるらしい。
私はこれを知らなかったため、jQuery の確認のところでうまく動かず、非常に時間をとられた。
いずれにせよ詳細は Turbolinks で検索していただきたいが、簡単に言うと、上記コードを書いた場合、リロードすれば jQuery は動くが、リンクから遷移すると動かない、という挙動になる。そもそも Turbolinks の存在も知らなかったため、私の目から見ると、jQuery が実行される時と実行されない時があって、挙動も一貫していないし、何が原因でこうなっているのか皆目見当がつかない、という状態だった。その結果、jQuery 等の導入手順に問題があるのかと思い、手順1 − 1から1 − 4を何回もやり直したりした。
ネットでひらすら調べ続けたところ、なんとかこうして原因を特定することができたのだが、私のような人を生み出さないためにもこの記事を書いた。
なお、先の手順2 − 1で示したコードは Turbolinks があっても毎回ちゃんと実行されるようにしてあるので(’turbolinks:load’が追記してある)、動くはずだ。
後日追記(js.erb 内で jQuery を使いたいとき) #
後日、link_to などで使える remote: true オプションおよび js.erb を使って Ajax を実装しようとしていたところ、js.erb 内で jQuery が使えずに手間取ったので、解決策を追記。対応はシンプルで、以下1行を追記するだけ。
対象のファイル
→ app/javascript/packs/application.js
window.$ = jQuery; // 最終行に左記を追加(必ずしも最終行である必要はないので場所はご自由に)
それにしても毎度毎度、jQuery 周りには手間を取られている気がする…
感想 #
今回のように、うまくいかないことに直面したときに、いろいろ調べて新たな知識を得るわけだが、それにしても解決までにかなり時間がかかってしまった。最終的には解決できたので、まだなんとか報われた気がする。