Rails & Webpackerを最大限活用するために知っておくべきことまとめ
Rails & Webpackerを最大限活用するために知っておくべきことまとめ:
Railsの新しいフロントエンドシステムとして登場したWebpackerについての知見をまとめていきますが、そもそもなぜWebpackerが必要となったのか、これまでのフロントエンド界隈の流れをまとめていきましょう。
もともとRailsのフロントエンド管理としては「Assert Pipeline」(+Sprockets)があり、画像・CSS・JSの静的ファイルを一括で結合&minifyまでやってくれる便利なツールとして重宝されていました。
当時はGruntやGulpといったnpmのビルドツールが競合として存在していましたが、Asset Pipelineは特に事前知識がなくともフロント周りを(当時の最適解として)管理してくれたので、Rails使いとしては必須のツールでした。
風向きが変わったのはJSとビルドツールの進化で、Browserifyの登場からフロントエンドにもモジュール管理の仕組みが普及し始めます。今では信じられませんが、フロントエンドでファイル間の機能を連携させるにはGlobalを通じて行うしかありませんでした。
そして今やデファクトとなったWebpackによって、JSだけでなくCSSや画像も含めた静的ファイルをモダンな手法でビルド可能になったことから、Asset Pipelineは時代に取り残された産物と見なされるようになりました。
懐かしさすら感じますが、npmのパッケージをGemfileに記述してAsset Pipelineから読み込んだり、BrowserifyをAsset Pipelineと連携させてモジュール管理をしたり、React Railsというパッケージでは力技でSSRを実行しようとする流れもありました。
しかし結局の所Asset Pipelineを保持したままJS界隈の進化にキャッチアップするのは困難であることから、徐々にAsset Pipelineを使わず、
「Railsはフロントエンド開発から取り残された」という見方が強くなる中、Railsがwebpackを自前のRailwayに取り込むためにWebpackerが登場しました。
WebpackerはRailsにWwbpackを導入するためのものなので、結論から言うと「webpackが使えるならWebpackerを無理に使う必要はない」と言えます。
だからと言って「Webpackerは絶対に使うべきではない」という訳でもありません。
メリットとデメリットがあるので、自分やチームの知識、プロジェクトの状況に合わせて使い分けるのが望ましいでしょう。いずれにせよWebpackerの特徴は抑えておくべき必要はあります。
Webpackerを使えばそれらを抽象化してくれる上、ReactやTypeScriptのような主要機能の導入もコマンド一つで完結するので、それこそ事前知識ゼロでもすぐに始められます。
またwebpackをRailsの中に取り込むことで、Asset Pipelineとの併用やwebpacker向けメソッドの提供、また「webpack-dev-server時にはcssを外す」等をよしなに行ってくれます。
もっとも上記のことは自前でメソッドを作るなり、yarnコマンドを定義すれば容易に実現できるので、強烈なメリットかと言われるとそうではないかもしれません。
反対にデメリットとしては次のようなことが考えられます。
ReactをWebpackerと統合すれば、ますますWebpackerに依存することになるため、導入コストの低さと、Webpacker依存による保守性の低下は隣り合わせになります。
またWebpackerは
これはwebpackの設定とはかなり毛色が異なり、ゴリゴリとカスタマイズするのならば、webpackとWebpacker両方の知識が要求されるのでかえって手間になる可能性があります。
webpackに熟練したエンジニアが「脱Webpacker」を掲げることがあるのはこれが要因で、息の長いプロジェクトであればあるほどWebpacker独自の作用に従うデメリットが大きくなりやすいでしょう。
要約するとWebpackerは導入コストの低さと、webpackをレールに乗せられることが利点、反対に保守性の低さとカスタマイズ性に難を抱えていますが、Railsというフレームワーク自身の特徴とも似ています。
先行きが分からない初期フェーズは開発工数を抑えるためにWebpackerを導入し、サービスがグロースして長期的な視点から開発できるようになったらwebpackに置き換えるのは現実的にアリでしょう。(webpackに明るいメンバーがいれば、正直最初からwebpackのほうが良い気がしますが)
Webpacker→webpackの移行は設定ファイルの作成、packageの整理くらいで既存の静的ファイルをいじる必要はありません。
webpackerは
ブラウザに描画しながら開発する分には、圧倒的にwebpack-dev-serverの開発効率の方が良いので、ぜひこちらを活用しましょう。
巷でDocker Composeを使ったサンプルコードを見ると、Railsにforemanを導入して、
具体的なケースとしては
同じコンテナを使って別サービスにするデメリットは特にないので、Rails用のサービスは
別サービスに分けた時にあるあるなハマリポイントとして、RailsがWebpackerが起動していることを検知できずにエラーを出してしまうことです。
これはWebpackerのREADMEにも書かれていますが、
例えば
webpack-dev-serverを使う場合、開発環境時のCSSは、JSによって出力されたblobファイルを読み込むため独立したファイルとして出力されません。
しかし時にはCSSのパスが欲しいことがあるかもしれません。そんな場合は以下のような設定ファイルを書いて、特定のCSSのみ明示的に出力すると良いでしょう。
上記のCSS設定のように、通常でないユースケースが出てくるとどうしてもwebpack自体の知識が必要ですが、レールに乗っかっていれば知識ゼロでもモダンな開発がすぐに取り組めるのは明確な利点でしょう。
「設定はすっ飛ばしてすぐにRailsで開発したい」という人にはオススメですし、「Rails以外でもwebpackを汎用的に使いたい」という人は自前でwebpackを導入した方が良いかもしれません。
皆さんの状況に合わせて臨機応変に使い分けて頂ければと思います。
Railsの新しいフロントエンドシステムとして登場したWebpackerについての知見をまとめていきますが、そもそもなぜWebpackerが必要となったのか、これまでのフロントエンド界隈の流れをまとめていきましょう。
Webpackerをなぜ使うのか
もともとRailsのフロントエンド管理としては「Assert Pipeline」(+Sprockets)があり、画像・CSS・JSの静的ファイルを一括で結合&minifyまでやってくれる便利なツールとして重宝されていました。当時はGruntやGulpといったnpmのビルドツールが競合として存在していましたが、Asset Pipelineは特に事前知識がなくともフロント周りを(当時の最適解として)管理してくれたので、Rails使いとしては必須のツールでした。
風向きが変わったのはJSとビルドツールの進化で、Browserifyの登場からフロントエンドにもモジュール管理の仕組みが普及し始めます。今では信じられませんが、フロントエンドでファイル間の機能を連携させるにはGlobalを通じて行うしかありませんでした。
そして今やデファクトとなったWebpackによって、JSだけでなくCSSや画像も含めた静的ファイルをモダンな手法でビルド可能になったことから、Asset Pipelineは時代に取り残された産物と見なされるようになりました。
懐かしさすら感じますが、npmのパッケージをGemfileに記述してAsset Pipelineから読み込んだり、BrowserifyをAsset Pipelineと連携させてモジュール管理をしたり、React Railsというパッケージでは力技でSSRを実行しようとする流れもありました。
しかし結局の所Asset Pipelineを保持したままJS界隈の進化にキャッチアップするのは困難であることから、徐々にAsset Pipelineを使わず、
frontend
のようなディレクトリに自前でWebpackを導入する流れが出てきます。「Railsはフロントエンド開発から取り残された」という見方が強くなる中、Railsがwebpackを自前のRailwayに取り込むためにWebpackerが登場しました。
WebpackがあればWebpackerは必要ないのか
WebpackerはRailsにWwbpackを導入するためのものなので、結論から言うと「webpackが使えるならWebpackerを無理に使う必要はない」と言えます。だからと言って「Webpackerは絶対に使うべきではない」という訳でもありません。
メリットとデメリットがあるので、自分やチームの知識、プロジェクトの状況に合わせて使い分けるのが望ましいでしょう。いずれにせよWebpackerの特徴は抑えておくべき必要はあります。
Webpackerのメリット
- webpackの設定を全く知らなくても、すぐにモダンな開発が行える
- Asset PipelineのようにRailsの一部として扱えるので、Railwayに沿って静的ファイルを扱える
Webpackerを使えばそれらを抽象化してくれる上、ReactやTypeScriptのような主要機能の導入もコマンド一つで完結するので、それこそ事前知識ゼロでもすぐに始められます。
またwebpackをRailsの中に取り込むことで、Asset Pipelineとの併用やwebpacker向けメソッドの提供、また「webpack-dev-server時にはcssを外す」等をよしなに行ってくれます。
もっとも上記のことは自前でメソッドを作るなり、yarnコマンドを定義すれば容易に実現できるので、強烈なメリットかと言われるとそうではないかもしれません。
Webpackerのデメリット
反対にデメリットとしては次のようなことが考えられます。- webpack本体だけでなく、React等もWebpackerの依存に引きずられる
- Webpacker独自の設定が辛いことがある
ReactをWebpackerと統合すれば、ますますWebpackerに依存することになるため、導入コストの低さと、Webpacker依存による保守性の低下は隣り合わせになります。
またWebpackerは
@rails/webpacker
という独自の設定ファイルを持っており、設定をカスタマイズするときにはこの設定を継承する必要があります。これはwebpackの設定とはかなり毛色が異なり、ゴリゴリとカスタマイズするのならば、webpackとWebpacker両方の知識が要求されるのでかえって手間になる可能性があります。
webpackに熟練したエンジニアが「脱Webpacker」を掲げることがあるのはこれが要因で、息の長いプロジェクトであればあるほどWebpacker独自の作用に従うデメリットが大きくなりやすいでしょう。
「とりあえずWebpacker」から後でwebpackに移行するのはアリ
要約するとWebpackerは導入コストの低さと、webpackをレールに乗せられることが利点、反対に保守性の低さとカスタマイズ性に難を抱えていますが、Railsというフレームワーク自身の特徴とも似ています。先行きが分からない初期フェーズは開発工数を抑えるためにWebpackerを導入し、サービスがグロースして長期的な視点から開発できるようになったらwebpackに置き換えるのは現実的にアリでしょう。(webpackに明るいメンバーがいれば、正直最初からwebpackのほうが良い気がしますが)
Webpacker→webpackの移行は設定ファイルの作成、packageの整理くらいで既存の静的ファイルをいじる必要はありません。
実際にWebpackerを使ってみての知見
開発時はwebpack-dev-serverを使うべし
webpackerは./bin/webpack
と./bin/webpack-dev-server
の2つのコマンドが用意されています。前者はリクエスト時に都度コンパイル、後者はwebpack-dev-serverの特徴ですが、ファイルをインメモリに保持し、変更時にライブリロードしてくれます。ブラウザに描画しながら開発する分には、圧倒的にwebpack-dev-serverの開発効率の方が良いので、ぜひこちらを活用しましょう。
Docker ComposeではRailsと別サービスにするのがオススメ
巷でDocker Composeを使ったサンプルコードを見ると、Railsにforemanを導入して、rails s
と./bin/webpack-dev-server
を同時起動しているケースがよく見られますが、とりたてて同時起動するメリットはないように感じます。具体的なケースとしては
yarn install
を実行した時にwebpackerがビルドしまくるのを防ぐためにサービスを停止すると、再起動時に全てのサービスを立ち上げ直す必要があります。単にDockerの不調で立ち上げ直したい時など、意外とwebpackerを再起動したい時があるので、その度に全サービスを立ち上げ直すと、時間の浪費にかかるストレスが大きかったです。同じコンテナを使って別サービスにするデメリットは特にないので、Rails用のサービスは
rails s
を、Webpacker用のサービスは./bin/webpack-dev-server
をそれぞれ独立して立ち上げるのがオススメです。
環境変数を忘れずに設定する
別サービスに分けた時にあるあるなハマリポイントとして、RailsがWebpackerが起動していることを検知できずにエラーを出してしまうことです。これはWebpackerのREADMEにも書かれていますが、
WEBPACKER_DEV_SERVER_HOST
という環境変数を設定すれば回避できます。例えば
webpacker
というサービスに分離した場合、railsサービスの環境変数を以下のように設定します。environment: WEBPACKER_DEV_SERVER_HOST: webpacker
開発環境時にもCSSのパスが欲しい時
webpack-dev-serverを使う場合、開発環境時のCSSは、JSによって出力されたblobファイルを読み込むため独立したファイルとして出力されません。しかし時にはCSSのパスが欲しいことがあるかもしれません。そんな場合は以下のような設定ファイルを書いて、特定のCSSのみ明示的に出力すると良いでしょう。
config/webpack/loaders/explicit-css.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { test: /[ファイル名]\.css$/, use: [ MiniCssExtractPlugin.loader, "css-loader", ] };
config/webpack/development.js
process.env.NODE_ENV = process.env.NODE_ENV || 'development'; const environment = require('./environment'); ~~ // 自前のloadersを追加する const explicitCSS = require('./loaders/explicit-css'); environment.loaders.append('explicitCSS', explicitCSS); ~~ const config = environment.toWebpackConfig(); config.devServer.watchContentBase = false; module.exports = config;
最後に
上記のCSS設定のように、通常でないユースケースが出てくるとどうしてもwebpack自体の知識が必要ですが、レールに乗っかっていれば知識ゼロでもモダンな開発がすぐに取り組めるのは明確な利点でしょう。「設定はすっ飛ばしてすぐにRailsで開発したい」という人にはオススメですし、「Rails以外でもwebpackを汎用的に使いたい」という人は自前でwebpackを導入した方が良いかもしれません。
皆さんの状況に合わせて臨機応変に使い分けて頂ければと思います。
コメント
コメントを投稿