Rails 6 Webpacker

3 mins read

There are few things to set up to make webpacker work with Rails 6.

Following work with Rails 6.1.0.alpha 526dd64 & Webpacker 4.2.2.

This file must be present per sprockets-rails#444.

{}

sprockets-rails#446 to make this an option so you can put in other places.

Comment/remove require of sprockets railtie in config/application.rb:

-require "sprockets/railtie"
+# require "sprockets/railtie"

Comment/remove all occurrences related to config.assets in development.rb and production.rb.

I recommend to have a app/webpacker directory (because we are going to have JS, CSS, assets files in this directory. Rails's default app/javascript seems weird, but you can choose not to fight with the framework). You need to tell Webpacker to find files in app/webpacker and turn on emits CSS.

# config/webpacker.yml
default: &default
  source_path: app/webpacker # app/javascript/ (default)

  # ...

  # Extract and emit a css file
  extract_css: true

With subdirectory of javascripts, packs, and stylesheets.

app
├── assets
│   └── config
│       └── manifest.js
└── webpacker
    ├── images
    │   └── logo.svg
    ├── javascripts
    │   └── application.js
    ├── packs
    │   └── application.js
    └── stylesheets
        └── application.scss

webpacker/packs/application.js will be the entry point to interact with Webpacker:

import 'javascripts/application'
import 'stylesheets/application'

This will import webpacker/javascripts/application.js and webpacker/stylesheets/application.scss.

webpacker/images will be the place to put images.
webpacker/javascripts will be the place to put JavaScript.
webpacker/stylesheets will be the place to put CSS.

webpacker/javascripts/application.js will be the entry to import all the JavaScripts (same role as good old app/assets/javascripts/application.js).

We can still have modular JavaScript (e.g. cable.js) and import it:

import "./cable"

webpacker/stylesheets/application.scss will be the entry to import all your stylesheets (same role as good old app/assets/stylesheets/application.scss).

We can still have modular css (e.g. _root.scss) and import it:

// webpacker/stylesheets/application.scss
import "root";

webpacker/images/ will be the directory to put all the images (same role as good old app/assets/images/).

Add the following to packs/application.js to import all images:

const imageContext = require.context('images/', true)
imageContext.keys().forEach(imageContext)

Reference your image with asset_pack_path helper in the view.

$ yarn add rails-ujs

Add following to webpacker/javascripts/application.js:

import Rails from "rails-ujs"
Rails.start()

$ yarn add turbolinks

Add following to webpacker/javascripts/application.js:

import Turbolinks from "turbolinks"
Turbolinks.start()

$ yarn add activestorage

Add following to webpacker/javascripts/application.js:

import * as ActiveStorage from "activestorage"
ActiveStorage.start()

$ yarn add actioncable

Add following to webpacker/javascripts/application.js:

// app/webpacker/javascripts/cable.js
import cable from 'actioncable'

window.App || (window.App = {})

window.App.cable = cable.createConsumer()

const context = require.context('./channels', true, /_channel\.js$/)
context.keys().forEach(context)

And put each JavaScript file (with suffix of _channel.js) for channel in webpacker/javascripts/channels folder.

$ yarn add stimulus

Put Stimulus controller files under webpacker/javascripts/controllers/ and the following to webpacker/javascripts/application.js to import them:

import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
const context = require.context("./controllers", true, /\.js$/)
application.load(definitionsFromContext(context))

Use the new *_pack_tag in the layout:

<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>

There is also asset_pack_path:

<img src="<%= asset_pack_path('images/logo.svg') %>">

Besides rails s, have another terminal tab with bin/webpack-dev-server. Webpacker automatically refresh your page and tell you if something went wrong during compliation of your front-end files. You can also use foreman to start both rails and webpack-dev-server.

That’s it!