はじめに
Railsが用意しているjavascript, css, 画像などのアセットを管理するGemに、Sprockets
とWebpacker
があります。
この2つを軽く説明すると、
名称 | 説明 |
---|---|
Sprockets | Rails3.1から導入されたアセットパイプライン。app/assets ディレクトリでアセットを管理する |
Webpacker | Rails6から導入された、WebpackというモジュールバンドラをRails用にラップしたgem |
WebpackerはSprocketsとの共存を考えて設計されており、Sprockets, Webpackerどちらも使うことを想定しています。
ただまあどちらもアセットを管理するgemなわけで、ややこしくなるしどちらか1つだけ使えばいいのでは?と僕は考えています。
以前作成したAsobiというWebアプリでも、Webpackerでアセットを管理したので、最終的にSprocketsが管理するapp/assets
ディレクトリを丸ごと削除しました。
次のWebアプリでもWebpackerを使う予定だったので、app/assets
を削除したのですが…
環境
- Ruby 2.7.0
- Rails 6.0.2
起きたこと
Sprockets
を使わないようにするための手順はいくつかありますが、最終的にapp/assets
というディレクトリは完全にいらなくなります。
なので最初にapp/assets
を削除しました。
$ rm -rf app/assets
試しにここでrails s
でRailsを起動しました。
ここでは正常にRailsサーバが起動すると思ったのですが…
WARNING: Nokogiri was built against LibXML version 2.9.10, but has dynamically loaded 2.9.4
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Exiting
Traceback (most recent call last):
# 中略...
/Users/user/rails_test/vendor/bundle/ruby/2.7.0/gems/sprockets-rails-3.2.1/lib/sprockets/railtie.rb:105:in `block in <class:Railtie>': Expected to find a manifest file in `app/assets/config/manifest.js` (Sprockets::Railtie::ManifestNeededError)
But did not, please create this file and use it to link any assets that need
to be rendered by your app:
Example:
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
and restart your server
どうやらapp/assets/config/manifest.js
が無いためSprockets::Railtie::ManifestNeededError
というエラー出てrails s
が終了したようです。
だが待ってほしい。これまでこんなエラー出てこなかったぞ?
原因
こちらのページによると、どうやらSprocketsのバージョンが4.0.0
になってから起きるようになったエラーのようです。
Redmine doesn't start with Sprockets::Railtie::ManifestNeededError if sprockets 4.0.0 is installed.
$ bin/rails c
Traceback (most recent call last):
28: from bin/rails:4:in<main>' 27: from bin/rails:4:in
require'
.
.
.
/Users/maeda/redmines/gems/ruby/2.6.0/gems/sprockets-rails-3.2.1/lib/sprockets/railtie.rb:105:inblock in <class:Railtie>': Expected to find a manifest file in
app/assets/config/manifest.js` (Sprockets::Railtie::ManifestNeededError)
But did not, please create this file and use it to link any assets that need
to be rendered by your app:Example:
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
and restart your server
Redmine doesn't start with Sprockets::Railtie::ManifestNeededError if sprockets 4.0.0 is installed.
と書いてありますね。
Sprocketsのissueにも同様のエラー報告がありました。
Actual behavior
An error is thrown since 4.0, this didn't occur on 3.7.2:rake aborted!
Sprockets::Railtie::ManifestNeededError: Expected to find a manifest file inapp/assets/config/manifest.js
But did not, please create this file and use it to link any assets that need
to be rendered by your app:Example:
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
and restart your server
3.7.2では起きなかったエラーとのことで、やはりSprockets 4.0.0から起きているエラーのようです。
対処法
Sprockets
のバージョンを3.7.2に下げる
バージョン4.0.0から起きているのであれば、バージョンを3.7.2に下げれはエラーが解消されるはず!
まずはGemfile
に以下のコードを追記します。
# Sprockets4.0だと、app/assetsディレクトリを削除するとSprockets::Railtie::ManifestNeededErrorが発生する
gem 'sprockets', '~> 3.7.2'
そしてbundle update
を実行します。(bundle installじゃないよ)
改めてrails s
を実行すると、無事エラーが解消されました。
$ rails s
WARNING: Nokogiri was built against LibXML version 2.9.10, but has dynamically loaded 2.9.4
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
/Users/user/rails_test/vendor/bundle/ruby/2.7.0/gems/actionpack-6.0.2.1/lib/action_dispatch/middleware/stack.rb:37: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/Users/user/rails_test/vendor/bundle/ruby/2.7.0/gems/actionpack-6.0.2.1/lib/action_dispatch/middleware/static.rb:110: warning: The called method `initialize' is defined here
Puma starting in single mode...
* Version 4.3.1 (ruby 2.7.0-p0), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
rails new
のオプションの--skip-sprockets
を指定する
rails new
のオプションに--skip-sprockets
というものがあります。
これを指定してRailsアプリを作成すると、config/application.rb
のrequireが一部変化します。
# --skip-sprocketsを指定した場合
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
# 指定しない場合、この1文のみ記述される
require 'rails/all'
require "sprockets/railtie"
がコメントアウトされています。
この状態であれば、app/assets
ディレクトリを削除してもSprockets::Railtie::ManifestNeededError
は発生しません。
余談 : --skip-sprockets
を指定してもSprocketsはインストールされる
Railsガイドに書いてありますが、この--skip-sprockets
はapplication.rb
の変更と一部のgemを除外してくれるだけです。
# Railsガイドで説明されている、除外されるgem
gem 'sass-rails'
gem 'uglifier'
gem 'coffee-rails'
上記の除外されるgemのリストにSprocketsはありません。
そう、--skip-sprockets
オプションでSprocketsを使わないRailsアプリを作成しても、Sprocketsはインストールされます。更にapp/assets
も生成されます。
これに関しては、GitHubのRailsにも以下のissueが投げられています。
The
app/assets
folder, and its underlying structure, is created, despite the fact that dropping stylesheets intoapp/assets/stylesheets
no longer causes them to be loaded. This is misleading, at best.
つまり、「--skip-sprockets
を指定したらapp/assets
を作らないようにした方が誤解がないのでは?」というissueが3年前に投げられています。
でも3年経っても変化はないので、恐らくこの状況を変えるつもりはないのでしょう。
まとめ
Sprockets
を使わないのであれば、Sprockets
のバージョンを3.7.2
に落としましょう。
もしくはrails new
のオプションで--skip-sprockets
を指定しましょう。
参考文献
https://www.redmine.org/issues/32223
https://github.com/rails/sprockets/issues/643
https://github.com/rails/rails/issues/29749
https://railsguides.jp/asset_pipeline.html