rails 本番環境のcompileエラーについて。[ActionView::Template::Error (The asset "application.css" is not present in the asset pipeline.):]


はじめに

この記事ではrailsの本番環境でのコンパイルエラーの解決方法と、開発環境と本番環境のコンパイルの違いについてまとめます。

結論

ActionView::Template::Error (The asset "application.css" is not present in the asset pipeline.):

上記のエラーが出た際には、ターミナルから以下を実行する

① bundle exec rails assets:precompile RAILS_ENV=production
② export RAILS_SERVE_STATIC_FILES=true
③ サーバーを再起動

解説

① bundle exec rails assets:precompile RAILS_ENV=production

上記のコマンドでプリコンパイが実行されます。
プリコンパイの流れは下記の通りとなっています。
1. 高級言語のコンパイル
2. 連結
3. 圧縮
4. publicディレクトリに配置

これだけだと私自身何のことか分からなかったので、上記に流れをもう少し丁寧に説明します。
1 app/assetsディレクトリ配下のscssなどの高級言語を、cssなどの言語に変換する。
2 変換したcssやjavascriptファイルを一つのファイルに連結する。
3 スペースや改行を削除し容量を減らす。
4 作成したファイルをpublic/assetsに配置する。

ではなぜこのような手順を踏まなければ本番環境でエラーが生じるのか。

それはwebブラウザには複数のファイルを連結して表示させる機能を持たないからです。

railsでは、cssやjavascript、画像ファイルはassetsディレクトリ配下にそれぞれ専用のディレクトリが配置され、その中に置かれます。

しかしそれはあくまで開発効率を上げる為であり、このままだとwebブラウザで表示させることができません。
なので上記のようにプリコンパイルを行うことによって、ブラウザ上で表示可能にさせることができます。

② export RAILS_SERVE_STATIC_FILES=true

このコマンドでは環境変数RAILS_SERVE_STATIC_FILESにtrueを入れることで、public配下のファイルを公開することができます。

① bundle exec rails assets:precompile RAILS_ENV=productionを実行すると上述の通り、プリコンパイルが実行され、作成したファイル(プリコンパイル済ファイル)はpublic/assets以下に配置されます。
しかし本番環境ではデフォルトで、public配下のファイルが公開されない設定になっていることがある為、②によって公開し、公開したファイルをブラウザが読み込めるように設定します。

※production.rbに記載されています。

config/environment/production.rb
 config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

本番環境と開発環境のコンパイル方法の違いについて

上記のように本番環境では、コマンドによってプリコンパイルを実行するしました。
しかし開発環境では、なぜコマンドによってプリコマンドを実行しないのか。
それはwebpacker.ymlの設定によるものです。

config/webpcker.yml
development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

webpacker.ymlを見るとdevelopmentとproductionではcompile:の設定が異なっています。

compile: trueにすると動的コンパイルが行われます。

動的コンパイルとは、public配下にコンパイル済ファイルが見つからない時、/assets配下のファイルを自動でコンパイルします。その為、開発環境では手動でコマンドを実行することなくコンパイルが行われます。
ですが、ユーザーがページにアクセス度にコンパイルが実行されればページの表示が遅くなります。
その為、本番環境では動的コンパイルが行わず手動でのプリコンパイルが推奨されます。

最後に

本番環境へのデプロイは苦手意識がありましたが、仕組みを知ればそこまで難しいことではありません!
同じビギナーさんの参考になればと思います。