But when I tried to introduce it to a Rails-newcomer, it struck me that making a switch from (or adding) webpack (and others) to an existing legacy Rails app is not that easy. Also, what's the sense of doing it anyway? We will try to make everything clear today.

What is webpacker?

Webpacker is a gem which provides integration with webpack and yarn in your Rails app.
From the webpack's page we can read that webpack is a static module bundler for modern JavaScript applications - in short, it's used to compile modern JavaScript modules so that our browser can understand it. That means we can use some ES6 code, as well as React, Angular, Vue, Elm or any other JS framework, and webpack will translate it into JavaScript.
Yarn, on the other hand, reads as fast, reliable, and secure dependency management - think of it as a bundler, but for your JavaScript modules.
Bear in mind that Webpacker's main purpose is to serve JavaScript, as well as assets like CSS, images and fonts for component-based JavaScript, but it is also possible to use it for your entire application's assets.

Psst, have you heard? Webpack is the new JavaScript bundler for Rails 6.0!

...which means that it will be no one else but webpacker to handle integration with Webpack and JS package managers such as yarn in the most recent version of the framework. Curious about other new features of Rails 6.0? Learn about Action Mailbox, Action Text, multiple database support, parallel testing and others from this article.

Let's get a bit technical

To install Webpacker in your legacy Rails application, simply add the gem webpacker to your Gemfile.

# Gemfile    
gem 'webpacker', '~> 3.5'

or if you prefer to use the master branch

# Gemfile  
gem 'webpacker', git: 'https://github.com/rails/webpacker.git'

After that, just run two commands in the terminal:

# bash
bundle install
bundle exec rake webpacker:install

When this is done, what is left to do is to add packs tag to our layouts, i.e. application, just like standard tags:

-# views/layouts/application.haml
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'application'

At this point, we are done with installing Webpacker in a legacy app - it's time to use some modern JS code!

But when you are creating a new app and want to have Webpacker installed right from the start, use this command when creating a Rails 5.1+ project:

# bash
rails new myapp --webpack

and you are good to go!

Quick note - if you are using Rails 5.2+, then you need to allow webpack-dev-server to load your packs. You can do this by adding this snippet to your CSP configuration:

# config/initializers/content_security_policy.rb
policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?

You might ask what is this webpack-dev-server, so let's pause for a second and explain it. When you are developing an application, Webpacker compiles your JS modules on-demand - so whenever you refer to any of your pack assets, it will compile it and serve it to your browser. But sometimes you just have too much JavaScript and on-demand compilation might be too slow to handle it - that is when webpack-dev-server comes in handy. It compiles all your packs upfront and also provides live code reloading - so whenever you make any change to your JS pack, it will recompile it. Using webpack-dev-server is very easy, because Webpacker comes up with binstub for it. All you have to do is run in your terminal (in your project directory), alongside your Rails server:

# bash

Throwing an eye on a new architecture

The structure for your newly created asset pipeline looks like this (taken from Webpacker's docs):

  ├── packs:
  │   # only webpack entry files here
  │   └── application.js
  └── src:
  │   └── application.css
  └── images:
      └── logo.svg

As you can see:

  • in packs we will have all of our JavaScript files
  • in src we will have stylesheets
  • in images we will have... images

To source images through webpack, you need to import them to your application.js (or any other file). You can do this by either normal import

// javascript/packs/application.js
import './images/some_image.png';

or if you have a big number of images, you can use require.context() to load all the files in a given folder

// javascript/packs/application.js
require.context('images', true, /\.(svg|png|jpg)$/igm);

Then to use them in your Rails template code, simply use the asset_pack_path helper, like this:

= image_tag asset_pack_path 'images/some_image.png'

End note: How your Rails app can benefit from webpacker?

Webpacker is a very powerful tool, opening multiple doors for us. We can now level up our application with a slick frontend, streamline user's experience and add new complex functionalities. Similarly to the i18l Ruby gem providing internationalization to your app, it increases your product's attractiveness in many ways. But this brief introduction is just only a beginning - in my next post, I will show you yet another new JS kid - StimulusJS. It will be a great example to present the capabilities of webpack and modern JS. Meanwhile, learn more on how we go about our Rails development process!

Photo by Annie Spratt on Unsplash.com

Recommended reads