Railsのstylesheet_link_tagとstylehseet_pack_tagの違いや使い所ついて調べてみた
株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。
Railsのstylehseet_pack_tag
とstylesheet_link_tag
の違いや使い所がよくわからなかったので、色々と試しながらまとめた記事になります。
一言でまとめると
stylesheet_link_tag
は、CSSをこれまでのRailsでの管理方法(Sprockets)で管理する際に記述する。つまり、CSSをapp/assets/stylesheets
内で管理する際に必要。
stylehseet_pack_tag
は、CSSをWebpackerで管理する際に記述する。つまり、CSSをapp/javascripts/stylesheets
で管理する際に必要。
デフォルト設定の場合
Ruby on Railsのv6系を指定し、rails new _6.0.0_ <アプリ名> -d mysql
した直後のプロジェクトのapp/views/layouts/application.html.erb
はデフォルトで以下のようになっています。
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
このデフォルトの状態で正常にCSSなどのファイルが読み込まれるのか確認するため以下の設定をしました。
-
app/javascript/packs/test.js
を作成し、console.log('test')
を記述 -
app/javascript/packs/appliction.js
に、imoprt 'packs/test'
を追記 -
app/assets/stylesheets/test.css
を作成し、body{color: red;}
を記述
※app/assets/stylesheets/application.css
には *= require_tree .
が記述されており、app/assets/stylesheets
のディレクトリ配下のCSSファイルは自動的に読み込まれますが、app/javascript/packs/application.js
にはそのような記述がないため、都度ファイルを読み込むための記述をします。(ディレクトリ以下を読み込む記述があれば教えていただきたいです。)
上記のように編集して、developmentモード、productionモードの各々の設定でrailsサーバーを起動してもエラーは起きず、追記したCSS・JSが反映された画面がエラーなく正常に表示されます。
productionモードの設定で起動するには以下の記事が参考になります。
※NginxなどのWebサーバーなどを使っていない場合には、config/environments/production.rb
の設定を以下のように変更します。
config.public_file_server.enabled = true
こちらの設定の詳細の中身は以下の記事に書かれていますのでご参考までに。
stylesheet_pack_tagがproduction環境でエラーが出る
デフォルト設定に以下のように stylesheet_pack_tag
を追記して、developmentモードでサーバーを起動しても特にエラーは起きませんでした。
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
しかし、この設定のままproductionモードでサーバーを起動するとエラーが起きてしまいます。つまり、開発時には特にエラーは起きていないのに、本番リリース時にはエラーが起きてしまうということになります。
エラーについては以下のログが吐き出されていました。
F, [2021-07-09T19:31:22.706284 #66663] FATAL -- : [e424266f-a5da-4358-b924-5cc0cbcb9258]
[e424266f-a5da-4358-b924-5cc0cbcb9258] ActionView::Template::Error (Webpacker can't find application.css in /Users/saitouryouzi/developer/jeans/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
unless you are using the `webpack -w` or the webpack-dev-server.
2. webpack has not yet re-run to reflect updates.
3. You have misconfigured Webpacker's config/webpacker.yml file.
4. Your webpack configuration is not creating a manifest.
Your manifest contains:
{
"application.js": "/packs/js/application-c3e3aae48c4c321181e9.js",
"application.js.map": "/packs/js/application-c3e3aae48c4c321181e9.js.map",
"entrypoints": {
"application": {
"js": [
"/packs/js/application-c3e3aae48c4c321181e9.js"
],
"js.map": [
"/packs/js/application-c3e3aae48c4c321181e9.js.map"
]
}
}
}
):
[e424266f-a5da-4358-b924-5cc0cbcb9258] 7: <%= csp_meta_tag %>
[e424266f-a5da-4358-b924-5cc0cbcb9258] 8:
[e424266f-a5da-4358-b924-5cc0cbcb9258] 9: <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
[e424266f-a5da-4358-b924-5cc0cbcb9258] 10: <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
[e424266f-a5da-4358-b924-5cc0cbcb9258] 11: <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
[e424266f-a5da-4358-b924-5cc0cbcb9258] 12: </head>
[e424266f-a5da-4358-b924-5cc0cbcb9258] 13:
[e424266f-a5da-4358-b924-5cc0cbcb9258]
[e424266f-a5da-4358-b924-5cc0cbcb9258] app/views/layouts/application.html.erb:10
開発(developmentモード)時にはエラーが起きなくて、本番(productionモード)時にはエラーが起きる理由は以下の記事に詳細が書いてありました。
javascript_pack_tag と stylesheet_pack_tag の仕様はこうなってます:development環境では、JavaScriptを使って動的にCSSを埋め込む。CSSファイルを生成してlinkタグに指定することはしない。
つまり、javascript_pack_tag
とstylesheet_pack_tag
はdevelopmentモードではlinkなどは生成していない。しかし、productionモードではlinkを生成する形になり、その参照先が何もないためエラーが発生するようです。
もっと正確に記述すると、config/webpacker.yml
の中でextract_css: true
の場合にはlinkを出力し、extract_css: false
の場合にはJavaScriptを使って動的にCSSを読み込むという動作になります。
GitHubでstylesheet_pack_tag
の実装を見てみると、そのようなコメントがありました。
When extract_css is false in webpacker.yml:
<%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # => nil
When extract_css is true in webpacker.yml:
<%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # => <link rel="stylesheet" media="screen" href="/packs/calendar-1016838bab065ae1e122.css" data-turbolinks-track="reload" />
実際に、config/webpacker.yml
の中身を見てみると以下のようになっています。(長いので関係ない箇所は省略しました。)
# Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default
source_path: app/javascript
source_entry_path: packs
public_root_path: public
public_output_path: packs
cache_path: tmp/cache/webpacker
webpack_compile_output: true
additional_paths: []
cache_manifest: false
extract_css: false
static_assets_extensions:
...
extensions:
...
development:
<<: *default
compile: true
production:
<<: *default
compile: false
extract_css: true
cache_manifest: true
development環境では、extract_css: false
となっており、production環境では、extract_css: true
となっています。
そのため、development環境ではJavaScriptで動的にCSSを読み込む形になっていました。
試しに、config/webpacker.yml
のdeveloment環境のextract_css: true
に設定して、ailsサーバーをdevelopmentモードで動かすと、さきほどproduction環境で出たエラーと同じエラーが発生しました。
stylesheet_pack_tagの使い所
stylesheet_pack_tag
の使いどころは、JavaScriptだけでなくCSSもWebpackerで管理したい時になります。(個人的な考えとして、Railsの標準ではそのような設定ではないので、極力CSSはWebpackerで扱わない方がいいのではないかと思っています。)
WebpackerでCSSを管理するのに必要な設定は以下の通りです。
-
stylesheet_link_tag
をstylesheet_pack_tag
に変更する -
app/javascript/application.js
に、利用したいCSSファイルをインポートする
今回はテストのために、app/javascript/stylesheets/test.css
を作成して、app/javascript/application.js
でimport 'stylesheets/test'
を記述してCSSが読み込まれるかテストしました。
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
body{
color: blue;
}
import 'stylesheets/test'
このようにして、developmentモード(config/webpacker.yml
のdevelopment環境はextract_css: false
に設定)でrailsサーバーを起動すると、エラーなどは起きずにCSSが正常に読み込まれていました。
これと全く同じ形でproductionモード(config/webpacker.yml
のdevelopment環境はextract_css: true
に設定)でrailsサーバーを起動してみても、エラーなどは起きずにCSSが正常に読み込まれていました。
参考記事
Discussion