Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 後編(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

タイトルは内容に即したものにしました。画像は元記事からの引用です。


更新情報

  • 2020/01/17: 初版公開
  • 2021/06/10: 更新

Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 後編(翻訳)

(前編からの続き)

Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 前編(翻訳)

今もJavaScriptコードをSprocketsで扱える

Webpackerドキュメントには以下のように書かれています。

(略)Webpackの主要な目的は「アプリのようなJavaScript」であり、画像やCSSのためではなく、ましてやJavaScript Sprinklesのためではない(これらは今後もapp/assetsの下に置ける)。
同ドキュメントより

つまり、ビューで何かJavaScriptを使いたいときや、使う必要に迫られたときは、これまでどおりSprocketsを使えるのです。

  • app/assets/javascriptsディレクトリを作成する(複数形の"javascripts"になっていることに注意)
  • app/assets/config/manifest.jsを上に合わせて更新する(//= link_directory ../javascripts .js
  • ビューにjavascript_include_tagを書いて、Sprockets用JavaScriptファイルをインクルードする(以下の違いに注意)
    • Sprockets用はjavascript_include_tag
    • Webpacker用はjavascript_pack_tag
  • 後は好きにやる

個人的にはこの手段をできる限り避けるようにしていますが、このことは知っておく価値があります。


原注: manifest.jsconfig.assets.precompileの配列は、どちらもコンパイル対象のトップレベルに露出させるという目的は同じなのに、どうしてファイルが2つもあるのかが気になる方もいらっしゃると思います。その目的は後方互換性のためです。Sprocketsのアップグレード手順では、後者をおすすめしていません。

Rails 6アプリケーションでbootstrap 4とfont-awesome 5を追加する手順

本記事をより深く理解いただくために、ここにある手順をそのまま適用することをおすすめします。JavaScriptの知見を深めるのに大いに役に立つでしょう。

1. Rails 6アプリケーションを新規作成する

rails new bloggy

以下にリストしたファイルを見てみましょう。目的は、皆さんにこれらを隅々まで理解してもらうことではなく、こういうファイルが存在するということを皆さんに知ってもらい、そこに何が含まれているのかというぼんやりとしたメンタルイメージを頭の隅に置いて、必要に応じていつでもそこに立ち返ることができるようにすることです。

Yarnのファイル:

  • package.json

Webpackerのファイル:

  • config/webpacker.yml
  • app/javascript/packs/application.js
  • app/views/layouts/application.html.erb

Sprocketsのファイル:

  • app/assets/config/manifest.json

2. ルートページを追加する

rails generate controller welcome index

ついでにconfig/routes.rbroot to: 'welcome#index'を追記します。

rails serverを実行し、問題なく動作することを確認します。

3. 必要なyarnパッケージを追加する

ここではBootstrap 4(jQueryとpopper.jsが必要です)とfont-awesome 5を追加したいと思います。

訳注(2021/06/10)

元記事はBootstrap 4を前提としていますが、その後Bootstrap 5がリリースされました。Bootstrap 5の場合は以下の手順と異なる部分がありますのでご注意ください。特にjQueryはBootstrap 5で必須でなくなっています

Yarnパッケージの検索エンジンで、自分に必要なパッケージを検索し(各パッケージのダウンロード数の多さに気づくことでしょう)、このチュートリアルを続行します。

yarn add bootstrap jquery popper.js @fortawesome/fontawesome-free

パッケージがyarnによって./bloggy/node_modules/にキャッシュされ、package.jsonも更新されます。しかしこのままではアプリケーションから利用できませんので対応しましょう。まずはJavaScript部分をインクルードすることにし、CSS部分は後でやることにします。

4. bootstrapとfont-awesomeのJS部分をインクルードする

アプリのレイアウトには既にjavascript_pack_tag 'application'が置かれています。これは、Webpackにapp/javascript/packs/application.jsのコンパイルを指示してその出力をレイアウトにインクルードします。bootstrapを追加するには、bootstrapをインクルードする専用のpackを別途作成するか、application.js packを使います。本物のアプリを作るわけではありませんので、ここでは後者をやってみましょう。

以下をapp/javascript/packs/application.jsに追加します。

require("bootstrap");
require("@fortawesome/fontawesome-free");

原注: ここでbootstrap/dist/js/bootstrap.minではなくbootstrapをrequireしていることにご注意ください。その理由は、ファイルパスを指定しない場合はどのファイルをインクルードすべきかという必要な情報をモジュールのpackage.json(つまりbloggy/node_modules/bootstrap/package.json)が提供するからです。bootstrap/dist/js/bootstrap.minをrequireすれば、それはそれで問題なく動くでしょう。


bootstrapとfont-awesomeの設定を続けましょう。Railsサーバーを起動してJavaScriptコンソールを開いてみると、application.jsでjQueryをrequireしていないにもかかわらず、問題なく動作していることを確認できます。

Webpackerを用いてbootstrapをインクルードする方法を他のチュートリアルで学んだ方の中には、他のチュートリアルのほとんどが最初にjQueryをrequireし、次にbootstrapをrequireしていることに気づいた方もいるかもしれません。これは実際には無意味です。

その理由がわかりますか?私たちはjQueryをyarnでインストールしているので、bootstrap自身がjQueryを自動でrequireできるのです。jQueryはapplication.jsの中で利用可能な状態になるので、jQueryをapplication.jsでrequireする必要はありません。すなわち、jQueryをapplication.jsの中で直接使う必要がない限り、実際にはjQueryをapplication.jsでrequireする必要はありません。

5. bootstrapとfont-awesomeの(S)CSS部分をインクルードする

私はSCSSを使うのが好きなので、bootstrapやfont-awesomeをインクルードする前にapplication.cssをapplication.scssにリネームし、コメントやSprockets用の指示を全部空にします。

続いて以下のコードを貼り付けます。

$fa-font-path: '@fortawesome/fontawesome-free/webfonts';
@import '@fortawesome/fontawesome-free/scss/fontawesome';
@import '@fortawesome/fontawesome-free/scss/regular';
@import '@fortawesome/fontawesome-free/scss/solid';
@import '@fortawesome/fontawesome-free/scss/brands';

@import 'bootstrap/scss/bootstrap';

原注: SprocketsはWebpackと異なり、インクルードするファイルを決定するためにnpmモジュールのpackage.jsonファイルを読み込みません。つまり、名前だけを指定してモジュールをインポートできません。実際にインポートしたいファイル名とそのパスを指定する必要があります(拡張子はあってもなくても構いませんが)。


ついに準備が整いました。

ビューに何かボタンとアイコンを追加して、問題なく動作しているかどうかを確認しましょう。

app/views/welcome/index.html.erbファイルに<a href="#" class="btn btn-primary">Yeah <i class="far fa-thumbs-up"></i></a>を追加してRailsサーバーを実行し、primaryボタンとアイコンがbootstrapらしく表示されていることを確認します。

jQueryをあらゆるpackで利用する

jQueryのような依存関係を多くのpackで使う必要が生じた場合、それらをpackごとにいちいちrequireするのは面倒です。私好みのソリューションは、設定を変えて全packで利用可能にすることです(繰り返しますが、あくまでpack内での話であり、ビューでは使えません)。

これを行うには、config/webpack/environment.jsに以下をコピペします。

const { environment } = require('@rails/webpacker')
var webpack = require('webpack');

environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
  })
)

module.exports = environment

このスニペットによって、WebpackはjQueryモジュールを$という名前を介して全packに「提供」します。これは、各packの冒頭に以下を追加するのと同等です。

import $ from 'jquery';

お読みいただいた皆さまに感謝いたします。

関連記事

Rails 6+Webpacker開発環境をJS強者ががっつりセットアップしてみた(翻訳)

Rails 5: Webpacker公式README — Webpack v4対応版(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。