個人のアプリケーションを今まではデフォルトのアセットまわり(CSS等)をSprockets、JavaScriptをWebpackerでビルドするような形にしてたのですが、
今回はstylesheetをWebpackerで管理するようにしたので、そのへんの手順をメモしておきます📝
対応したアプリケーションのRailsのバージョンは6.0.3.2、Webpackerのバージョンは5.1.1です。
.cssファイルをWebpackerで管理する
今回は.css(.scss)ファイルをWebpackerで管理するための手順をまとめていきます。
assets配下の.cssファイルをjavascript配下に移動
まずはSproketsで管理しているapp/assets配下の.cssファイルをWebpackerで管理するためにapp/javascript配下に移動します。
※webpacker.ymlでentryまわりの変更している場合は、その設定に従って移動先を指定してください。
今回はWebpackerの公式のドキュメントがapp/javascript/stylesheets配下においてそうだったので、そこに移動するようにしました🙋
# https://github.com/rails/webpacker/blob/master/docs/css.md
app/
javascript/
stylesheets/
application.scss
posts.scss
comments.scss
entryの.jsで.cssファイルをimportしてWebapckerのビルド対象にする
Webpacker(Webpack)はentryでimportされたファイルをビルド対象とするので必要な.cssファイルを
entryの.js(デフォルトだとapp/javascript/packs配下のjs)でimportしてあげます。
※Webpackerはデフォルトでsass-loader、css-loader等がinstallされて設定もよしなにしてくれるようです。
// app/javascript/application.js import '../stylesheets/application.scss'
Webpacker v5からはpacks配下にentryのjsと同名のcssを配置すると自動でimportしてくれるようになったようです、便利✨
By Webpacker convention (as of Webpacker v5), this will bundle application.js and application.scss as part of the same entry point (also described as a multi-file entry point in the webpack docs). https://github.com/rails/webpacker/blob/master/docs/css.md#importing-css-as-a-multi-file-pack-webpacker-v5
これでbin/webpack時にimportしたcssファイルがビルドされて読み込まれるようになりました🙌
しかしデフォルトだとhead内に直接ビルドされたstyleが記述されてしまいます。
styleが比較的軽量な場合は問題ないのですが、S3から.cssファイルを配信するため別ファイルで出力したいケースは多いかと思います。
.cssファイルを個別のファイルとしてビルドするようにする
Webpackerにはmini-css-extract-pluginを使用してimportしたファイルを個別ファイルで出力する機能が提供されています。
使用するためにはwebapcker.ymlのextract_cssをtrueに設定することで.cssファイルを個別のファイルとして出力することができます。
default: &default # Extract and emit a css file extract_css: true development: &default # Extract and emit a css file extract_css: true // その他環境でも必要に応じて同様に設定
Viewでビルドされた.cssファイルを読み込む
個別に出力された.cssファイルはjavascript_pack_tagと同様にView側の読み込む必要があります。
cssの場合はstylesheet_pack_tagを使って読み込みを行います。
<%= stylesheet_pack_tag 'application' %>
これで.cssファイルをWebapckerでビルドして個別ファイルに出力し、それをView側で読み込むことができるようになりました🎉
おまけ:eslintの対象からCSSまわりを除外する
package.jsonのlintまわりの設定を下記のような形にしていたのですが、javascript配下のcssがeslintの対象となってしまい。。。🤔
"scripts": { "lint": "eslint app/javascript/**/* --ext .vue,.js,.ts", "lint-fix": "eslint app/javascript/**/* --ext .vue,.js,.ts --fix",
色々調べてみたところ--extオプションがファイル指定の場合に効かないようで、、、eslintignoreで指定するようにしたのですが、
app/javascript/stylesheets
Note: --ext is only used when the arguments are directories. If you use glob patterns or file names, then --ext is ignored. https://eslint.org/docs/user-guide/command-line-interface#ext
これでは、eslintがeslintignoreと実行時の指定のどちらを優先すればいいかわからず、warning File ignored because of a matching ignore pattern. Use "--no-ignore" to override.の警告が発生してしまいます😢
If you pass a specific file to ESLint, then you will see a warning indicating that the file was skipped. https://eslint.org/docs/user-guide/configuring#ignored-file-warnings
最終的には下記のようなディレクトリ指定にして--extオプションが効くようにして対応しました🙇♂️
"scripts": { "lint": "eslint app/javascript --ext .vue,.js,.ts", "lint-fix": "eslint app/javascript --ext .vue,.js,.ts --fix",
おまけ: Sproketsの無効化
アセットまわりもWebpackerでビルドするようにするとSproketsはもう必要ないので無効化してあげると依存gemも減らせていい感じです。
※ちなみに新規にアプリケーションを作る場合は--skip-sproketsを指定してrails newすればOKなので楽です👌
Sproketsのrequireをやめる
application.rbでrequire 'rails/all'をしているとsprockets/railtieもrequireされてしまうので、
%w( #... sprockets/railtie ).each do |railtie| begin require railtie # https://github.com/rails/rails/blob/6-0-stable/railties/lib/rails/all.rb#L18
sprockets/railtieを除いて個別にrequireするようにします。
require 'active_record/railtie' require 'active_storage/engine' require 'action_controller/railtie' require 'action_view/railtie' require 'action_mailer/railtie' require 'active_job/railtie' require 'action_cable/engine' require 'action_mailbox/engine' require 'action_text/engine' require 'rails/test_unit/railtie'
config系のファイルからassetsまわりの設定値を削除する
その後config/enviroments配下の各ファイルからconfig.assets関係の設定を削除していきます。
各設定値の詳細はこちら
(config.assets.enabledをfalseにしといた方がいいのかな?🤔)
私の個人アプリだとこの辺の設定を削除しました。
# config/environments/development.rb config.assets.debug = true # 削除 config.assets.quiet = true # 削除 # config/environments/production.rb config.assets.compile = false # 削除
そして、config/initializers/assets.rbも削除します。
sass-railsをGemfileから削除する
最後にGemfileからsass-railsを削除してbundle installします。※uglifier等も残っていたら削除します。
gem 'sass-rails', '>= 6' # 削除
これでSproketsも無効化できました🎉
おわりに
今回はstyleまわりを例にAssets PipelineからWebpakerに移行する手順をちょっと整理してみました。(今回行ったのは.cssだけだったのでシンプルでしたが、実際の案件ではこんなにすんなりはいかなさそう。。。)
Webpack移行の前段としてSproketsとの併用をやめて、Webpacker単体の環境に移行しておくと移行対象が減るので、いいかもですね👀