Replacing Rails Asset Pipeline with WebpackerAugust 04, 2017
I'll admit that I'm still relatively new to Rails Webpacker, but on a new project I've decided to completely replace the Sprockets asset pipeline and instead handle all my assets through Webpacker. As a fellow convention over configuration fan I've tried my best to interpret what the convention for structuring a Webpacker app is - I think it's still early days and even the Rails team haven't worked it out yet. I suspect it's something the community will nut out over time. Nonetheless, here is how I've replaced the asset pipeline in my app.
If you're starting fresh, run
rails new blank --skip-sprockets --webpack to kick off a new Rails app without Sprockets and with Webpacker. If you need to add Webpacker to an existing project then read up on the docs. Then remove some gems from your 'Gemfile' you're not going to need -
coffee-rails. You can also ditch
app/assets as you're not going to be using that anymore.
First, let's take a look at the default
application.js generated by Webpacker.
If you read the comment it's pretty clear that the
This is how I've organised my Webpacker app - for an example app called
Now let's take a look at my
This will go import and run
Keep in mind you aren't going to call your directory (and filename) blog as well, you'll match the name of your Rails app for simplicity. Otherwise of course you can call it whatever you like.
I'm just popping this in here because it seems to have confused some of the people I've spoken to on the issue. When in development run
bin/webpack-dev-server - this will watch changes to your app and rebuild when required, pushing changes to the browser. When you're ready to compile you can call
rails assets:precompile but you're likely to leave that up to your server.
Turbolinks and Rails UJS
The next thing to tackle (if you're using either of these features) is to get Turbolinks and Rails UJS back up and running. In the asset pipeline it's as simple calling
//= require but it's a little different when using them as modules. First, install both the NPM packages.
yarn add rails-ujs turbolinks
Then we need to import and start them up, in our
import Rails from 'rails-ujs'; import Turbolinks from 'turbolinks'; Rails.start(); Turbolinks.start();
As you can see they use the same signature to kick them off after you've imported them. Pretty easy.
You can access your environment variables from your scripts as they are compiled. I used to append
.erb to the filename and then do something like
<%= ENV['X_ENV_VAR'] %> but there is a better way. Environment variables are exposed to
export const STRIPE_API_KEY = process.env.STRIPE_API_KEY;
You can simply import the CSS or Sass stylesheets you want to use. I've been popping my Sass entry point in
While on this topic, it's worth learning about the
~ character when using imports as it will start a lookup from the
node_modules directory. So if you wanted to import something like Bootstrap it's as easy as the following.
Boom - Bootstrap 4 ready to go!
import './logo.svg'; import './menu-open.svg'; import './menu-close.svg';
Keep in mind this won't actually include the images in your stylesheets, it'll just pull them in through Webpacker so they're available to your app. You can then use the
asset_pack_path helper in your views to reference the files. So, if you wanted to use one of those images you could do something like...
= image_tag asset_pack_path('logo.svg')
In addition you can reference your images in your CSS/Sass and Webpacker will automatically hook them up for you. Generally the root path will be the entry point to your CSS so you shouldn't need to use absolute paths or anything funky.
This is pretty much a work in progress, it's more of a snapshot of how I'm using Webpacker now. I tried to find other posts about how people are using Webpacker but there's not much out there at the moment. I'm really interested to see what the standard use of Webpacker will look like, or if we'll even come to some sort of standard at all.
A blog about Laravel & Rails, written by Dwight Watson.