Learn Clould Application Development and DevOps

The Blackninja Blog

Expand your Cloud Application Development and DevOps knowledge with detailed tutorials and case studies.

Webpacker Webpack, Webpacker and Modules, Oh My! How to Add Javascript to Ruby on Rails

I don’t think anyone would have ever said using the Asset Pipeline in Rails was easy, but now with Webpacker, learning to add Javascript to Ruby on Rails is definitely worth the effort.

With the Asset Pipeline one of the biggest pain points was getting your require statements correct. Mostly because you had to use something called Sprockets and learn syntax like:

          
            //= require sub/something
          
        

Seriously that looks like something that’s commented out, but actually it will have some pretty negative effects on your productivity if you get it wrong…

Thankfully, with Webpacker all the challenges we had with Sprockets and the Asset Pipeline are still there! Now they just have WAY MORE documentation!

  • We still need to figure out how to require our javascript
  • We still need to know where to put our javascript
  • We still need to learn about some gem

To be fair, I wouldn’t expect big advancements to requiring our Javascript or knowing where to put it. Wouldn’t you agree that the big difference between a good programmer and great one is knowing where to put things? That’s an evergreen skill. As opposed to learning Sprockets. Learning Sprockets is like going deep on the manual for your toaster. You might be able to create the most delicate and refined cooked bread in your house, but your toasting skills will be rendered useless by the first not-my-toaster you encounter. That’s Sprockets.

The big change is that the gem we need to learn about is Webpacker. Webpacker is Webpack. Webpack is basically the defacto tool for bundling Javascript assets for usage in a browser. In fact, Webpack can bundle just about any asset at this point. So now the mental gymnastics required to add Javascript to your Rails project will actually build skills you can use in any framework! Instead of learning your toaster, its like going to Culinary School.

Ready to re-learn everything you knew about adding Javascript to Rails? Me too! Let’s do it!

You probably came here hoping to just get that snippet you could use to solve your problem and move on. I get it. So we aren’t going to go deep on Webpack.

I’m going to show you 5 quick ways to add Javascript to a Rails application that uses Webpacker.

I’ve found that these 5 ways work for most of the cases I encounter.

In a few of these examples I’m going to use Yarn to add the javascript library to our application. Yarn knowledge is like Git knowledge. 90% of all the developers in the world know 5 git commands. You literally only need to know 3 things about yarn to get started:

  1. Webpacker looks for Javascript in a folder called node_modules by default
  2. yarn add adds the Javascript library to the node_modules folder
  3. yarn remove removes the Javascript library from the node_modules folder
Option 1: Adding Javascript to application.js

I’d call this the quick and dirty option. You probably don’t want to clutter your application.js with all your front-end logic, but hey, deadlines right? So let’s use good ol’ jQuery as an example:


      yarn add jquery
      


This will add the jQuery module to your node_modules folder. Next, let’s actually require the module in application.js:


      // app/javascript/packs/application.js

      // CommonJS Syntax
      var jQuery = require("jquery")

      // ES6 Syntax
      import jQuery from "jquery"
      


Choose one of these syntaxes and stick with it. You don’t want to be one of those people that sometimes uses import and sometimes uses require.

Notice I declared a variable for the CommonJS Syntax. The defaults in the application.js file make you think you don’t need to do this, until you actually try to use the jQuery module. For this example I could have also made it $.

Now let’s smoke test our module by printing the version number in the console:


      // app/javascript/packs/application.js
      // ...
      console.log(jQuery.fn.jquery)
      


So that’s Option 1. Why wouldn’t you do this? Well, first because it might not work (if it doesn’t you probably need to do Option 5). Second, because adding all your Javascript to application.js is going to get you hated at work pretty much immediately. So let’s look at separating your code from application.js

Option 2: Adding Javascript as a Pack

Without knowing anything about Webpack (the blue pill), this option allows you to include your code on a Layout page separately from the standard application bundle. So let’s say you only want to use React or Vue for a specific part of your Rails application, you could use this to only include it there. Knowing we are using Webpack (the red pill), this method creates an entry point. What’s an entry point? Go read your brains out.

To add our previous code that printed the jQuery version to the console we would remove our code from application.js and simply add it to a new file in the packs directory:


      // app/javascript/packs/custom.js
      var jQuery = require("jquery")
      console.log(jQuery.fn.jquery)
      


If you go ahead and refresh your browser page, you will notice that the version isn’t printed anymore. That’s because we added our code to the packs folder but we haven’t added a script tag to our layout that references our pack! Here’s how you do that:


      <-- app/views/layouts/application.html.erb -->
      <%= javascript_pack_tag 'custom', 'data-turbolinks-track': 'reload' %>
      


Refresh and now our version number is printing again! Problem is, adding that script tag was exhausting. There must be a way to do this without needing to add that…

Option 3: Adding Javascript as a Module

Maybe you want to require your code like a module. The same way you would if it was added with yarn. That’s what this option does and no script tag!

Technically the packs folder is for packs. If that’s not for you, then you can simply create a folder underneath the javascript folder and under that create a file named index.js. The folder name becomes the name of your module that you will use in require or import statements. Here’s the same code from the last option, ported to that index.js file:


      // app/javascript/custom/index.js
      var jQuery = require("jquery")
      console.log(jQuery.fn.jquery)
      


Now instead of a script tag, we simply add a require statement to our application.js:


      require("custom")
      


It works! (I’m assuming).

Ok, get ready to add Webpack to your resume because our next option is going to show you how to add Javascript to your rails application by actually doing some Webpack configuration!

Option 4: Adding Javascript to environment.js

So there was a reason I used jQuery as the example. If you are using jQuery you probably want to use it throughout your Javascript files. You probably don’t want to require or import it everywhere. So how could we add it globally to all of our Javascript files? If you said “I would use Webpack’s plugin architecture to include jQuery in my webpacker environment.js file!” then why are you reading this article… If you didn’t say that, then…

Webpack has a ProvidePlugin that can be configured to include jQuery globally. In Rails, you do this in the environment.js file inside the config/webpack directory:


      // config/webpack/environment.js
      const webpack = require('webpack');
      environment.plugins.prepend(
        'Provide',
        new webpack.ProvidePlugin({
          $: 'jquery',
          jQuery: 'jquery'
        })
      )
      


Now you can simply run the previous console statement we’ve been using in all of our examples with NO require or import of the jquery module in those files.

Obviously this option should be reserved for something like jQuery and it should be done with some careful consideration. Because every file will have this module automagically included in it, its not obvious where its coming from. That could lead to some frustrating moments when your co-workers are baffled as to how jQuery continues to be included in the bundle.

Option 5: Adding Javascript to the vendor directory

Yes! You can still just drop your Javascript in the vendor directory and move on with life. In fact, this is probably the solution you need if the Javascript library you are trying to add isn’t working for any of the other options. Let’s call this the Duct Tape Programmer option.

For this example I’m going to use Donutty.js. Why? Because the sample code on codepen for this library will not work if you try using the previous 4 options. We all have a Donutty in our project. A library we’ve learned and love and wrote thousands of lines of code against… then DHH makes Webpack the default and strikes at the very thing we hold most dear. Well you can strike back by bypassing all his fancy Webpack and using the good ol’ vendor directory.

So, since I called this the Duct Tape Programmer option, let’s go all in on that analogy. We aren’t going to use Yarn. We are going to take a look at the CDN that’s being used by that example, pull it down, and copy to our vendors directory.

In CodePen the CDN URL can be found by clicking the Settings button and choosing the Javascript tab:

Copy that url, and then in your Terminal, cd into the vendor directory and run a curl command:


      curl https://cdn.rawgit.com/simeydotme/donutty/288831fd/dist/donutty.js -o donutty.js
      


Webpacker is a snob by default and won’t look for files in your vendor directory, but we can fix that with a simple change to the webpacker.yml file inside the config directory. Simply add vendor as a path:


      # config/webpacker.yml
      # ...
      # Additional paths webpack should lookup modules
      # ['app/assets', 'engine/foo/app/assets']
      resolved_paths: ['vendor']
      


Now all we have to do is require the file in our application.js file. To do that, simply require the name of the file without the extension:


      require('donutty')
      


Awesome! The CodePen example works! Honestly, how many times have you tried to port a CodePen example into Rails and its been a dumpster fire. Just use the vendor directory and live the life you’ve always dreamed of.

(Awesome music plays…)

So there you have it! 5 ways to add Javascript to your Rails project using Webpacker. You should feel pretty damn confident about adding Javascript to your Rails application now…