When to use stylesheet_pack_tag instead stylesheet_link_tag with Rails 6

Viewed 9552

When creating a new rails project with Rails 6, it creates an application.html.erb with stylesheet_link_tag to load CSS and javascript_pack_tag for javascript files.

Now, rails 6 also provide a stylesheet_pack_tag, so my question is, when to use it? And if we use it, do we need to add all CSS files in app/javascript folder?

What is the best practice to load css, images with rails 6 and webpacker?

2 Answers

You should use stylesheet_pack_tag if you are importing any CSS in Webpack AND if you have enabled extract_css: true for any environment in config/webpacker.yml.

Given the following directory structure:

app/
  javascript/
    packs/
      application.js
    styles/
      site.css

And the following code in application.js:

import '../styles/site.css'

You would use <%= stylesheet_pack_tag 'application' %> in your view, i.e., the name of the stylesheet matches the name of the "pack".

At this point, I also recommend renaming app/javascript to something like app/frontend. So, the key changes in config/webpacker.yml:

source_path: app/frontend
extract_css: true
app/
  frontend/
    packs/
      application.js
    styles/
      site.css

Just to try to clarify this a little. This is based on my current understanding, which seems to work well enough but still might not be fully accurate.

CSS processed by the asset pipeline gets a css_link_tag and css that is imported via a Webpacker javascript bundle is referenced with css_pack_tag.

Asset pipeline css is in app/assets/stylesheets. Webpack css is in app/javascripts/wherever_you_want.

So in webpack, all of the css imported into a javascript bundle is eventually extracted to a servable file that can be referenced via the same name as the js bundle.

So if in app/javascripts/application.js you have:

import 'app/javascripts/css/one.css'
import 'app/javascripts/css/two.css'
import 'app/javascripts/css/three.css'

These will be referenced with

css_pack_tag 'application'

This comes out looking like this in my deploy logs

Entrypoints:
  application (430 KiB)
      css/application-9d82d487.css
      js/application-9f45d7ff735a7a203f28.js

It also bears noting, as was mentioned above that this behavior is affected by the extract_css setting.

Presumably this is false in development by default and true in production. One big GOTCHA with this is that, at least in my case, the css_pack_tag wasn't actually "required" in development, in the sense that removing it had no effect because it wasn't extracted locally. It still "worked" because the css was loaded in the javascript and seemed to be applied somehow that way. So I removed these tags thinking they were unnecessary before my understanding improved. Unfortunately when I deployed to production on heroku some time later, none of my css was working and it took me a while to figure out why and remember that I had removed these css_pack_tag lines.

Related