Skip to content

Instantly share code, notes, and snippets.

@tduyng
Last active March 29, 2021 19:42
Show Gist options
  • Save tduyng/425cf6df7f0d04890b93503d8893be53 to your computer and use it in GitHub Desktop.
Save tduyng/425cf6df7f0d04890b93503d8893be53 to your computer and use it in GitHub Desktop.

Assets, Webpacker and Rails 6. Why your images and css aren’t showing up.

Rails 6 is full of fun awesome new features and some new ways of compiling our assets. Heroku is one of the easiest way to deploy your rails application but things between development and production can get a little hairy if you’re not careful with a couple of gotchas that exist with the way we compile and use assets in production making your site look weird by having missing pictures or css that just don’t load. Throw in two ways off compiling assets now with Webpacker and Sprockets and things getting even more complicated.

Images in your assets directory

The first thing you need to do with any asset your you want to use like images that are in your assets folder is to use the asset_path helper or asset_url helper instead of a hardcode link to the path.

So image tag that might look like this in your erb file:

<img src="/assets/my_image.png"> 

Needs to change to look like this:

<img src=<%=asset_path("my_image.png")%>

If you have rule sets in you scss files that require an image in your assets image folder you will have to use the asset-url helper. A background image property in your application.scss file will need to be changed from this:

body {
    background-image: url("/assets/cool_image.png");
}

Will need to be changed to this:

body {
    background-image: asset-url("cool_image.png");
}

Not doing the above will probably work fine on your local development environment but will break on your production environment. This is because your local environment doesn’t have the compiled images with their hashed named.

Therefore /asset/cool_image.png will be in its location locally but might look like this in in your production environment /asset/cool_image123h53jh2358uigjeru894lasen49.png

SCSS and CSS Please Work

One thing you want to do is stick to just one place for your scss.

Your css can live in /app/assets/stylesheets directory

.OR. in your /app/javascript/ folder you want to create a new folder and call it src or stylesheets or whatever you want.

DO NOT put styles in both places unless you want to have a bad time. If you do you will have to use two links in your layouts application folder which will give you many hours of frustration trying to make it all work.

I recommend sticking your css files in /app/asset since the Webpacker documentation clearly states that you probably should unless your working with component based javascript (like React, Vue, Angular etc…) From the WebPacker Docs:

It[WebPacker] coexists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets).

What to do

The easy and recommended way keep it in assets

If you decide to to put your scss in your /app/assets/stylesheets directory then you must make sure that in your /app/views/layouts/application.html.erb you have the stylesheet being linked like this

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

That is the default way that the css stylesheet will be loaded when you create your app so no need to change anything there. However if you installed other things using Webpacker like Bootstrap or Fontawesome and did not use sprockets and the asset pipeline you will have to also use the the stylesheet_pack_tag.

Below I will go over how to use SCSS / CSS with webpacker and properly import your stylesheets. The difficult and NOT recommended way (by me atleast)

Using Webpacker to compile your SCSS

If you want to put your scss files in your /app/javascript/whatever_folder then you must change the /app/views/layouts/application.html.erb to the following:

<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

Notice the difference in between the methods, this time around its pack_tag where before it was link_tag. Now you must tell Webpack yourself what you want to import.

In /app/javascript/packs/application.js Let’s say you want to import your scss files that you created above from whatever folder you created. So if you have a scss file in /app/javascript/packs/stylesheets/my_stylesheet.scss then you must have

import "./stylesheets/my_styleshees.scss" 

in your application.js file. In your application.js file is also where you would load up anything else that you wanted to load using WebPack instead of using the asset pipeline.

Ref

Medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment