简体   繁体   中英

Rails 5.1 with Webpacker. Using custom js classes

I'm playing with rails 5.1 and i'm having trouble using a custom class from webpacker in an asset pipeline js file.

My thought was that if I had some utility js class that I wanted to use everywhere I'd add it in packs and then be able to use it in anything on the webpacker side as well as everything on the pipeline side.

// app/javascript/packs/stuff.js
class Stuff {
  constructor() {
    console.log("*** building stuff! **")
  }
}
export default Stuff

If I want to use that on the webpacker side I can with just adding this to

packs/application.js
import Stuff from "./stuff"
let s = new Stuff()

No issues there, but then I try to use that class on the pipeline side and I get

Uncaught ReferenceError: Stuff is not defined

I'm using it like this:

// assets/javascripts/users.js
new Stuff();

I've added to my layout file:

= javascript_pack_tag 'stuff'

And I also tried adding to the pipelines application.js

//= require stuff
//= require_tree .

stuff.js was compiled properly to public/packs/stuff.js and is in the manifest.json

{
  "application.js": "http://0.0.0.0:8080/packs/application.js",
  "hello_react.js": "http://0.0.0.0:8080/packs/hello_react.js",
  "stuff.js": "http://0.0.0.0:8080/packs/stuff.js" 
}

I've also added this to the assests.rb initializer:

Rails.application.config.assets.paths << Rails.root.join('public/packs')

I'm sure i'm missing something small and have just been looking at it for too long to see it.

----- UPDATE -----

There is a little noise in the original post as I was flailing trying to get stuff to work. In the end you just need the tip provided by the accepted answer.

In app/javascript/packs/application.js add:

import Stuff from "./stuff"
window.Stuff = Stuff

And in your layout make sure to have:

= javascript_pack_tag 'application'

I didn't need to //= require stuff in the pipeline application.js. I also didn't need to add the public directory in the assets.rb initializer.

To use in a pipeline js file like users.js just make sure you use it after everything has loaded like this:

$( document ).on('turbolinks:load', function() {
  new Stuff();
})

Or if you want to inline it in your index.slim or something you can just do:

javascript: 
   new Stuff();

Once it is setup correctly you'll want to restart the webpack server:

./bin/webpack-dev-server

Now if you make changes to stuff.js they should be compile and available right away as you would expect.

My final stuff class looks like this:

export default class Stuff {
  constructor() {
    console.log("*** building stuff! **")
  }

  more() {
    console.log("--- more stuff ---")
  }
}

You have to declare your imported class in window in order to use it in your front-end code (asset or in template). In your pack application.js add the following :

import Stuff from "./stuff"
window.Stuff = Stuff

Then you can use it :

var foobar = new window.Stuff();

Full stack example here : https://gist.github.com/Aschen/f0a53b0d522688cc46ef77705074c1d2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM