本ガイドではWebpackerのインストール方法と、Railsアプリケーションのクライアント側で用いるJavaScriptやCSSなどのアセットをWebpackerで利用する方法について解説します。ただしWebpackerの開発は終了した点にご注意ください(訳注: 移行方法は末尾の参考資料をご参照ください)。
このガイドの内容:
Webpackerは、汎用的なwebpackビルドシステムのRailsラッパーであり、標準的なwebpackの設定と合理的なデフォルト設定を提供します。
webpackなどのフロントエンドビルドシステムの目的は、開発者にとって使いやすい方法でフロントエンドのコードを書き、そのコードをブラウザで利用しやすい方法でパッケージ化することです。webpackは「JavaScript」「CSS」「画像やフォント」といった静的アセットを管理できます。webpackを使うと、「JavaScriptコードの記述」「アプリケーション内の他のコードの参照」「コードの変換(トランスパイル)や結合」をダウンロードしやすいpackにまとめられます。
詳しくはwebpackのドキュメントを参照してください。
RailsにはSprocketsも同梱されています。SprocketsもWebpackerと同様のアセットパッケージングツールで、Webpackerと機能が重複しています。どちらのツールも、JavaScriptをブラウザに適したファイルにコンパイルすることでproduction環境でのminifyやフィンガープリント追加を行えます。development環境では、SprocketsもWebpackerもファイルをインクリメンタルに変更できます。
SprocketsはRailsで使われる前提で設計されているため、統合方法はWebpackerよりもシンプルで、Ruby gemを用いてSprocketsにコードを追加できます。webpackは、より新しいJavaScriptツールやnpmパッケージとの統合に優れており、より多くのものを統合できます。新しいRailsアプリは「JavaScriptはwebpackで管理する」「CSSはSprocketsで管理する」設定になっていますが、webpackでCSSを管理することもできます。
新しいプロジェクトで「npmパッケージを使いたい場合」「最新のJavaScript機能やツールにアクセスしたい場合」は、Sprocketsではなくwebpackerを選択すべきでしょう。「移行にコストがかかるレガシーアプリケーション」「gemで統合したい場合」「パッケージ化するコードの量が非常に少ない場合」は、WebpackerではなくSprocketsを選ぶべきでしょう。
Sprocketsに慣れ親しんでいる方は、以下の表を参考に両者の対応関係を理解するとよいでしょう。なお、ツールごとに構造が微妙に異なっているため、必ずしも概念が直接対応しているとは限らない点にご注意ください。
タスク | Sprockets | Webpacker |
---|---|---|
JavaScriptをアタッチする | javascript_include_tag |
javascript_pack_tag |
CSSをアタッチする | stylesheet_link_tag |
stylesheet_pack_tag |
画像にリンクする | image_url |
image_pack_tag |
アセットにリンクする | asset_url |
asset_pack_tag |
スクリプトをrequireする | //= require |
import またはrequire
|
Webpackerを使うには、Yarnパッケージマネージャー(1.x以上)とNode.js(10.13.0以上)のインストールが必要です。
WebpackerはnpmとYarnに依存しています。npm(Node Package Manager)レジストリは、Node.jsとブラウザランタイムの両方で、主にオープンソースのJavaScriptプロジェクトの公開やダウンロードに用いられるリポジトリです。npmの位置づけは、Rubyのgemを扱うrubygems.orgに似ています。Yarnコマンドラインユーティリティは、RubyのBundlerと位置づけが似ています。BundlerがRubyの依存関係のインストールや管理を行うのと同様に、YarnはJavaScriptの依存関係をインストールおよび管理できます。
新規プロジェクトにWebpackerを含めるには、rails new
コマンドに--webpack
を追加します。
既存のプロジェクトにWebpackerを追加するには、プロジェクトのGemfile
にwebpacker
gemを追加してbundle install
を実行し、続いてbin/rails webpacker:install
を実行します。
ファイルとフォルダ | 場所 | 説明 |
---|---|---|
JavaScriptフォルダ | app/javascript |
フロントエンド向けJavaScriptソースコードの置き場所 |
Webpacker設定ファイル | config/webpacker.yml |
Webpacker gemを設定する |
Babel設定ファイル | babel.config.js |
Babel(JavaScriptコンパイラ)の設定 |
PostCSS設定ファイル | postcss.config.js |
PostCSS(CSSポストプロセッサ)の設定 |
Browserlistファイル | .browserslistrc |
Browserlist(対象ブラウザを管理する)設定 |
また、インストールコマンドはyarn
パッケージマネージャを呼び出してpackage.json
というファイルを作成し、基本的なパッケージセットのリストをこのファイルに含めます。これらの依存関係はYarnでインストールされます。
Webpackerをインストールすると、app/javascript/packs
ディレクトリ以下のJavaScriptファイルがコンパイルされて独自のpackファイルにまとめられます。
たとえば、app/javascript/packs/application.js
というファイルが存在すると、Webpackerはapplication
という名前のpackを作成します。このpackは、<%= javascript_pack_tag "application" %>
というERBコードが使われているRailsアプリケーションで追加されます。これによって、development環境ではapplication.js
が変更されるたびに再コンパイルされ、ページを読み込むとコンパイル後のpackが使われます。実際のpack
ディレクトリに置かれるのは、主に他のファイルを読み込むマニフェストファイルですが、任意のJavaScriptコードも置けます。
RailsのデフォルトJavaScriptパッケージがプロジェクトに含まれていれば、Webpackerで作成されたデフォルトのpackはそのデフォルトJavaScriptパッケージにリンクします。
import Rails from "@rails/ujs" import Turbolinks from "turbolinks" import * as ActiveStorage from "@rails/activestorage" import "channels" Rails.start() Turbolinks.start() ActiveStorage.start()
これらのパッケージをRailsアプリケーションで使うには、これらのパッケージをrequire
するパックをインクルードする必要があります。
app/javascript/packs
ディレクトリにはwebpackのエントリーファイルだけを置き、それ以外のものを置かないことが重要です。webpackはエントリーポイントごとに個別の依存関係グラフを作成するので、packを多数作成するとコンパイルのオーバーヘッドが大きくなります(アセットのその他のソースコードはこのディレクトリの外に置くべきです: Webpacker自身はソースコードの構造に制約をかけませんが、適切なソースコード構造を提案することもありません)。以下はソースコード構造の例です。
app/javascript: ├── packs: │ # ここにはwebpackエントリーファイルだけを置くこと │ └── application.js │ └── application.css └── src: │ └── my_component.js └── stylesheets: │ └── my_styles.css └── images: └── logo.svg
通常、packファイル自体はimport
やrequire
で必要なファイルを読み込むマニフェストですが、いくつかの初期化を行うこともあります。
これらのディレクトリを変更したい場合は、config/webpacker.yml
ファイルのsource_path
(デフォルトはapp/javascript
ディレクトリ)とsource_entry_path
(デフォルトはpacks
ディレクトリ)も変更してください。
JavaScriptソースファイル内のimport
ステートメントは、インポートするファイルの位置を「相対的に」解決します。つまり、import Bar from "./foo"
と書くと、現在いるディレクトリにあるfoo.js
ファイルを探索しますが、import Bar from "../src/foo"
と書くとsrc
という名前の親ディレクトリにあるファイルを探索します。
Webpackerでは、PostCSSプロセッサを用いてCSSやSCSSのサポートを即座に利用できます。
CSSコードをpackにインクルードするには、まずCSSファイルをトップレベルのpackファイルにインクルードします(JavaScriptファイルをインクルードするときと同じ要領です)。つまり、CSSのトップレベルマニフェストがapp/javascript/styles/styles.scss
にある場合は、import styles/styles
でインポートします。これにより、webpackがCSSファイルをダウンロードに含められるようになります。実際にWebページで読み込むには、ビューのコードに<%= stylesheet_pack_tag "application" %>
を追加します。
CSSフレームワークを用いる場合は、フレームワークをyarn
でnpmモジュールとして読み込むインストール手順(yarn add <フレームワーク名>
が典型)に従えば、Webpackerにフレームワークを追加できます。たいていのフレームワークには、CSSやSCSSファイルにインポートする手順があるはずです。
Webpackerのデフォルト設定では、画像やフォントなどの静的アセットもすぐに使えるようになっています。この設定には画像ファイルやフォントファイルのフォーマットに対応する拡張子が多数含まれており、webpackはそれらの拡張子も生成されたmanifest.json
ファイルに追加します。
webpackのおかげで、以下のコード例のように静的アセットをJavaScriptファイル内で直接インポートできます。インポートされた値は、そのアセットへのURLを表します。
import myImageUrl from '../images/my-image.jpg' // ... let myImage = new Image(); myImage.src = myImageUrl; myImage.alt = "I'm a Webpacker-bundled image"; document.body.appendChild(myImage);
Webpackerの静的アセットをRailsのビューで参照する必要がある場合は、WebpackerにバンドルされるJavaScriptファイルで明示的にrequire
する必要があります。Sprocketsとは異なり、Webpackerはデフォルトでは静的アセットをインポートしない点にご注意ください。デフォルトのapp/javascript/packs/application.js
ファイルには、指定のディレクトリからファイルをインポートするテンプレートがコメントの形で用意されているので、静的ファイルを置きたいディレクトリごとにコメント解除して利用できます。ディレクトリはapp/javascript
を起点とする相対パスです。テンプレートではimages
というディレクトリ名になっていますが、app/javascript
の中であれば任意のディレクトリ名に変更できます。
const images = require.context("../images", true) const imagePath = name => images(name, true)
静的アセットは、public/packs/media
ディレクトリ以下に出力されます。たとえば、app/javascript/images/my-image.jpg
にある画像をインポートすると、public/packs/media/images/my-image-abcd1234.jpg
に出力されます。この画像のimage
タグをRailsのビューでレンダリングするには、image_pack_tag 'media/images/my-image.jpg
を使います。
Webpackerで静的アセットを扱う場合のAction Viewヘルパーについては、以下の表でアセットパイプラインのヘルパーとの対応を確認できます。
ActionViewヘルパー | Webpackerヘルパー |
---|---|
favicon_link_tag |
favicon_pack_tag |
image_tag |
image_pack_tag |
asset_pack_path
というジェネリックなヘルパーも利用できます。このヘルパーにローカルファイルのパスを渡すと、Railsのビューで使えるWebpackerパスを返します。
また、app/javascript
のCSSファイルから直接ファイルを参照して画像にアクセスすることもできます。
バージョン5の時点のWebpackerは「Railsエンジン対応」ではありません。つまりWebpackerは、Railsエンジンで利用できるSprocketsと機能的な互換性がありません。
Railsエンジンgemの作者がWebpackerの利用をサポートする場合は、フロントエンドアセットをgem本体に追加してnpmパッケージとして配布し、ホストアプリケーションとの統合方法を説明する指示書(またはインストーラ)を提供することが推奨されます。Alchemy CMSは、このアプローチの良い例です。
Webpackerは、webpack-dev-serverでのHMR(Hot Module Replacement)をすぐ利用できるようになっており、webpacker.yml
ファイルでdev_server/hmr
オプションを設定することで切り替えられます。
詳しくはwebpackのDevServerドキュメントを参照してください。
ReactでHMRをサポートするには、react-hot-loaderの追加が必要です。詳しくはReact Hot LoaderのGetting Startedガイドを参照してください。
webpack-dev-serverを実行していない場合は、HMRを必ず無効にしてください。そうしないと、CSSで"not found error"エラーが発生します。
Webpackerにはデフォルトでdevelopment
、test
、production
の3つの環境があります。webpacker.yml
ファイルに環境設定を追加することで、環境ごとに異なるデフォルトを設定できます。また、Webpackerは環境設定を追加するためにconfig/webpack/<environment>.js
ファイルを読み込みます。
Webpackerには、development環境で実行する./bin/webpack
と./bin/webpack-dev-server
という2つのbinstubファイルが同梱されます。これらのbinstubファイルは、標準の実行ファイルであるwebpack.js
とwebpack-dev-server.js
の薄いラッパーになっており、環境に応じて適切な設定ファイルや環境変数が読み込まれるようになっています。
development環境のWebpackerは、デフォルトでRailsページが読み込まれると必要に応じて自動的にコンパイルを行います。つまり別のプロセスの実行は不要であり、コンパイルエラーは標準のRailsログに出力されます。これを変更するには、config/webpacker.yml
ファイルをcompile: false
に変更します。bin/webpack
を実行すると、packを強制的にコンパイルします。
コードのライブリロード機能を使いたい場合や、JavaScriptコードが多くてオンデマンドのコンパイルが遅くなる場合は、./bin/webpack-dev-server
またはruby ./bin/webpack-dev-server
を実行する必要があります。webpack-dev-serverのプロセスは、app/javascript/packs/*.js
ファイルの変更を監視して変更時に自動的に再コンパイルし、ブラウザを再読み込みします。
Windowsユーザーは、これらのコマンドをbundle exec rails server
とは別のターミナルで実行する必要があります。
このdevelopmentサーバーを起動すると、Webpackerが自動的にすべてのwebpackアセットリクエストをこのサーバーにプロキシします。サーバーを停止すると、オンデマンドのコンパイルに戻ります。
Webpackerドキュメントには、webpack-dev-server
を制御する環境変数の情報が記載されています。また、rails/webpackerのwebpack-dev-server利用法ドキュメントにある追加の注意事項も参照してください。
Webpackerはbin/rails assets:precompile
のrakeタスクにwebpacker:compile
タスクを追加するので、assets:precompile
を使う既存のデプロイパイプラインはすべて動作します。webpacker:compile
タスクはpackをコンパイルしてpublic/packs
に配置します。
Webpackerでメジャーなフレームワークを利用する方法などの高度な話題については、Webpackerドキュメントを参照してください。
Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。
原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨
本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。
Railsガイド運営チーム (@RailsGuidesJP)
Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。