Webpacker 6

Webpacker was officially retired before the official v6.0.0 was released following the release of Rails 7. Shakapacker is the official, actively maintained successor to Webpacker now.

Since the final version was never released, this post has been archived and will not receive further updates. The original upgrade guide was in multiple steps, but have been combined here for convenience.

Before we start the upgrade process for Webpacker 6, we are going to create a small demo application for us to work on.

If you are upgrading an existing app or not using this series as a tutorial, you can skip this step! We will begin the formal upgrade process in the next article.

Generate a new Rails app

First we will generate new Ruby on Rails app:

rails new webpacker_6 --skip-sprockets --skip-spring --skip-webpack-install --skip-bundle
cd webpacker_6

--skip-sprockets: Skip Sprockets files

--skip-spring: Don’t install Spring application preloader

--skip-bundle: Don’t run bundle install

--skip-webpack-install: Don’t run Webpack install

Setup the Database

bin/rails db:prepare

Turn off asset scaffolding

Prevent Rails from creating asset files when running the generators and scaffolds:

# config/application.rb

# ...
module Webpacker6
class Application < Rails::Application
config.load_defaults 6.1
+ config.generators do |g|
+ g.assets false
+ end
end
end

Add Pages Controller

Generate pages controller with a home action:

bin/rails g controller pages home

Add Root Route

Set pages#home as the root route:

# config/routes.rb

Rails.application.routes.draw do
get 'pages/home'
+ root to: 'pages#home'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

Note: Because we skipped the Webpacker install task, you will get an error if you try to start the application as is. We will fix that in the next article.

Updating our Gemfile

Update the gem in your Gemfile:

# Gemfile

- gem 'webpacker', '~> 5.0'
+ gem 'webpacker', '~> 6.0.0.beta.2'

Next, run bundle install to install the new gem version. If all goes well, you should see Using webpacker 6.0.0.beta.2 (was 5.2.1) in the install output.

Installing in our Application

Run the installation command, bin/rails webpacker:install, to generate the required configuration files, as well as update our package.json

Update Document Head

Lastly, let’s update app/views/layouts/application.html.erb. The docs for Webpacker v6 recommend using the javascript_packs_with_chunks_tag tag.

<%# app/views/layouts/application.html.erb %>

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

Verify Installation

Run the Rails server (bin/rails s) and the Webpack Dev Server (bin/webpack-dev-server) via your preferred method. Two terminal tabs will work or create a Procfile and run via overmind or foreman. The Rails server will also compile your assets if the dev server is not running, but this is much slower vs running separate processes and not recommended.

Visit http://localhost:3000 in your browser. If all’s well, you should see the contents of app/views/pages/home.html.erb.

We can verify our JavaScript is getting loaded by adding the following to app/javascript/packs/application.js:

// app/javascript/packs/application.js

console.log("Hello from Webpacker!")

Open the browser console and reload the page and you should see the message we added:

[Log] Hello from Webpacker! (application-7fbebc85af7886af0a64.js, line 62)

In order to process .css files with Webpacker 6, you need to add css-loader, style-loader, and mini-css-extract-plugin.

Install

yarn add css-loader style-loader mini-css-extract-plugin

Usage

Add a stylesheet_packs_with_chunks_tag or stylesheet_pack_tag to the document head.

Make sure you restart bin/webpack-dev-server after installing new loaders.

Style Loader Example

<%# app/views/layouts/application.html.erb %>

+ <%= stylesheet_packs_with_chunks_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload' %>

Extract Example

<%# app/views/layouts/application.html.erb %>

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

// app/javascript/packs/application.js

+ import "./application.css"

Verify

Note: Make sure you restart the dev server!

Let’s create a new file for our CSS:

touch app/javascript/packs/application.css

Next, add some CSS:

/* app/javascript/packs/application.css */

h1 {
font-size: 2.2em;
color: #2563eb;
}

p {
font-size: 1.2em;
}

Reload your browser and your styles should be applied now, and the Webpacker loader error should be gone.

In order to process .pcss files with Webpacker 6, you need to add postcss-loader. I am also going to add PostCSS 8 support.

Install

yarn add postcss-loader postcss@latest autoprefixer@latest postcss-import@latest

Add PostCSS Config File

touch postcss.config.js

// postcss.config.js

module.exports = {
plugins: [
require('postcss-import'),
require('autoprefixer')
]
}

Usage

You should be able to use the same pack tag that you added for CSS.

Make sure you restart bin/webpack-dev-server after installing new loaders.

Style Loader Example

<%# app/views/layouts/application.html.erb %>

+ <%= stylesheet_packs_with_chunks_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload' %>

Extract Example

<%# app/views/layouts/application.html.erb %>

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

// app/javascript/packs/application.js

+ import "./application.css"

Verify

Note: Make sure you restart the dev server!

Let’s create a new PostCSS file:

mkdir app/javascript/stylesheets
touch app/javascript/stylesheets/base.pcss

Next, add some CSS:

/* app/javascript/stylesheets/base.pcss */

h1 {
font-size: 2.2em;
color: #2563eb;
}

p {
font-size: 1.2em;
}

Lastly, update application.css:

/* app/javascript/packs/application.css */

@import "../stylesheets/base.pcss";

Reload your browser and your styles should be applied now, and the Webpacker loader error should be gone.

In order to process .scss and .sass files with Webpacker 6, you need to add sass-loader and sass.

Note: This section builds on the CSS section

Install

yarn add sass-loader sass

Usage

You should be able to use the same pack tag that you added for CSS.

Make sure you restart bin/webpack-dev-server after installing new loaders.

Style Loader Example

<%# app/views/layouts/application.html.erb %>

+ <%= stylesheet_packs_with_chunks_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload' %>

Extract Example

<%# app/views/layouts/application.html.erb %>

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

// app/javascript/packs/application.js

+ import "./application.scss"

Verify

Note: Make sure you restart the dev server!

Let’s create a new SCSS file:

touch app/javascript/packs/application.scss

Next, add some SCSS:

/* app/javascript/packs/application.scss */

$body-background: #fafafa;
$body-color: #444;

body {
background: $body-background;
color: $body-color;
font-family: sans-serif;
}

h1,
nav,
footer {
text-align: center;
}

main {
margin: 4rem auto;
max-width: 60rem;
}

Reload your browser and your styles should be applied now, and the Webpacker loader error should be gone.

In order to use your images and SVG files with Webpacker 6, you need to put them in the correct place and import them into your context.

Install

We should be good here.

Usage

Add Assets

mkdir -p app/javascript/media/images

Require Context

// app/javascript/packs/application.js
+
+ function importAll(r) {
+ r.keys().forEach(r);
+ }
+ // Add relevant file extensions as needed below.
+ // I'm sure there is a better way :shrug:
+ importAll(require.context('../media/images/', true, /\.(svg|jpg)$/));

Verify

Note: Restart the dev server for good luck!

Add an SVG and PNG into app/javascript/media/images

In one of your views, add two image tags:

<img src="<%= asset_pack_path 'media/images/icon.svg' %>" />
<img src="<%= asset_pack_path 'media/images/surf.jpg' %>" />

Reload your browser and you should see your images.

Note that <%= asset_pack_path 'media/images/icon.svg' %> only returns a string, so if you would rather inline your SVG files you will need to refer to the Webpack Asset Modules documentation and merge your changes into your Webpack context, as explained in these Webpacker docs.