Rails5.1から導入されたwebpackerにより、容易にモダンなフロントエンド開発環境を構築することが可能になりました。
中でも、webpack-dev-serverに寄って提供されているHMR(Hot Module Replacement)はフロントエンド開発の効率を大幅に向上させてくれるため、非常に重宝します。
Rails5.1では、このwebpack-dev-serverに関する設定もデフォルトで行われており、大変助かるのですが、デフォルトの設定ではJavaScriptしかサポートしてくれていません。
JSのフレームワークなど使っていれば、JS内でCSSを書くことも可能ですが、JSのフレームワークなんて知らねーよ!とか、ちょっとしたアプリ作るのにわざわざフレームワークなんて使わねーよ!とか、でもCSSもHMRしたい!ということはあると思います。(自分はありました。)
なので、自分と同じようなめんどくさがりな方々に向けて、Rails5.1でCSSをwebpack-dev-server管理化に置くために行なった設定を書いておきたいと思います。
(間違ってる。もっといい方法がある。そもそもデフォルトの機能で出来ますよ?等々あれば教えてください!)
では早速
なにはともあれ、まずはrails new
webpackerを使用する場合、rails new アプリ名 --webpack
といったように、普段のコマンドに--webpack
オプションを加えます。
既に作成済みのアプリケーションに適用する場合は
# Gemfileに追記
gem 'webpacker'
bundle install
rails webpacker
です。
webpackのエントリポイントを変更する
デフォルトのエントリポイントはapp/javascripts/packs
になっています。
CSSもwebpackの管理下に置きたいのでjavascripts
はやめたいです。
そのためには以下の二つの手順が必要です。
- フォルダ名を変更する
- config/webpack/paths.ymlを変更する
フォルダ名を変更する
app/javascripts/packs
をapp/frontend/packs
に変更しましょう。
frontendのところはなんでもいいですが、わかりやすくfrontendとしておきます。
JSファイルとCSSは分けたいので、Railsよろしく、その中にjavascripts
フォルダとstylesheets
フォルダを作成し、application.js
とapplication.scss
を作成しましょう。
paths.ymlを変更する
paths.ymlはwebpack用のdatabase.ymlのようなものです。
エントリポイントなどを管理しています。
デフォルトでは以下のようになっていますが
default: &default
config: config/webpack
entry: packs
output: public
manifest: manifest.json
node_modules: node_modules
source: app/javascripts
ファイル名の変更に伴い、以下のように変更します。
default: &default
config: config/webpack
entry: packs
output: public
manifest: manifest.json
node_modules: node_modules
source: app/frontend
manifest.jsonを変更する
manifest.jsonは、コンパイルしたファイルを配信するパスとprefix(であってるのか?)を管理するファイルです。
prefixは後で使います。
manifest.jsonを以下のように編集してください。
{
"javascripts/application.js": "http://localhost:8080/packs/javascripts/application.js",
"javascripts/application.js.map": "http://localhost:8080/packs/javascripts/application.js.map",
"stylesheets/application.css": "http://localhost:8080/packs/stylesheets/application.css",
"stylesheets/application.css.map": "http://localhost:8080/packs/stylesheets/application.css.map"
}
このmanifest.jsonですが、本来webpackerによって動的に生成されるものなんですが、今回はこれで固定したいので、設定を変更します。
config/webpack/shared.jsの40行目をいじります。
new ManifestPlugin({ fileName: paths.manifest, publicPath, writeToFileEmit: true })
// を
new ManifestPlugin({ fileName: paths.manifest, publicPath, writeToFileEmit: false })
// こう
これで固定できました。(絶対にもっといい方法ある。)
JSとCSSの読み込み先を変更
デフォルトだと、今まで通りAssets Pipelineようのヘルパーが定義されているので、変更します。
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
を
<%= stylesheet_pack_tag 'stylesheets/application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'javascripts/application', 'data-turbolinks-track': 'reload' %>
こう
ここで、manifest.jsonで定義したprefixを使用しています。
ここまでの作業が完了したら
rails s
bin/webpack-dev-server
をそれぞれ別タブで走らせて、ブラウザを開いた状態でpacks下のapplication.jsとapplication.scssを変更すると、リアルタイムで変更が反映されているのがわかります。
※ Railsの初期ページ(Yay! You’re on Rails!のページ)だと読み込まれないので、気をつけてください。
公式のドキュメントをあんまり読んでいないので、ツッコミどころあるかと思いますが、ぜひツッコんでください。
stylesheet_pack_tag
なんてのがあるくらいなので、もっとデフォルトの機能で出来そうな気がするのですが、知ってる方がいたら教えてほしいです。