Search code examples
javascriptruby-on-railsecmascript-6webpacker

Javascript compilation in Ruby on Rails 6


I'm using RoR 6.1.0, and would like to add a Javascript library. As a test case, I'll try to add JQuery. I am using webpacker to manage the Javascript libraries in my app.

First I use yarn to add jquery to the project:

yarn add jquery

Next I import jquery in the webpacker application entry point, app/javascript/packs/application.js. The second line verifies the import:

import jQuery from "jquery";
console.log(jQuery.fn.jquery);

My custom javascript files are saved in app/asets/javascripts. I create the file app/assets/javascripts/test.js as:

import jQuery from "jquery";

function test() {
    console.log(jQuery.fn.jquery)
}

Finally, in my view, I include test.js and assign the function to a button:

<%= javascript_include_tag('test.js') %>
<button onclick="test()">Button</button>

On page load, the console displays the following error: Uncaught SyntaxError: Cannot use import statement outside a module. I think this means the file test.js is not being processed by the ES6 compiler. How can I make sure that the javascript files in app/assets/javascript are compiled properly?


Solution

  • If you are using webpacker and you want to include js files in your views/layouts then you have to use javascript_pack_tag. All these files (called entries) should be under /packs (or where you set the source_path & source_entry_path in your webpacker.yml). The entries should import or require different files (bundle them) then webpacker will prepare them to be browser ready (babel, loaders, transpiling, etc..)

    Create app/javascript/packs/test.js and add these:

     require('app/assets/javascripts/test.js')
    

    This should fix the complilation issue. Webpacker has resolved_paths: [] in webpacaker.yml where you can add different paths to look for files. You can add app/assets/javascripts and change to:

    require('test.js')
    

    Now clicking that button. If you want to do it that way then test() should be on window. Another option is to bind an onClick event for that button at document ready. There are other options but these 2 are the easy ones.