2
votes

In a Rails project, I am trying switch from using the old Sprockets asset pipeline to using webpacker. I have set up these test files:

app/javascript/lib/foo.js

function foo() {
  console.log('foo')
}
console.log('bar')

app/javascript/packs/application.js

// some standard Rails JS requires
// ...
require('lib/foo')

app/views/test/index.html

<script>
  foo()
</script>

And in my layouts/application.html.erb I have

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

When I go to that page in my browser, I see "bar" logged to my console, followed by

"ReferenceError: foo is not defined"

I have tried a few different approaches to setting up my files, like using import instead of require or setting module.exports = foo or export default foo in my js file, but I haven't had any luck getting around the above error message.

So in short, how do I move javascript files from sprockets to webpacker? And if possible, how do I do so without changing my existing javascript code?

1

1 Answers

3
votes

You'll want to export functions and modules as a named export from your application.js pack and extend the Webpack config output to designate the library name and target var (or window will also work).

// config/webpack/environment.js

environment.config.merge({
  output: {
    library: ['Packs', '[name]'], // exports to "Packs.application" from application pack
    libraryTarget: 'var',
  }
})

// app/javascript/packs/application.js
import foo from '../lib/foo'

export {
  foo
}
<script>
 $(document).ready(function(){
   Packs.application.foo();
 });
</script>

The library name is arbitrary. Using the [name] placeholder is optional but allows you to export to separate modules if you're using multiple "packs".