Rails 5.1 с Webpacker. Использование пользовательских классов js

Я играю с rails 5.1, и у меня возникли проблемы с использованием настраиваемого класса из webpacker в js-файле конвейера ресурсов.

Я думал, что если бы у меня был какой-то служебный класс js, который я хотел бы использовать везде, я бы добавил его в пакеты, а затем смог бы использовать его во всем на стороне веб-упаковщика, а также во всем на стороне конвейера.

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

Если я хочу использовать это на стороне веб-упаковщика, я могу просто добавить это в

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

Здесь нет проблем, но затем я пытаюсь использовать этот класс на стороне конвейера и получаю

Uncaught ReferenceError: Stuff is not defined

Я использую это так:

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

Я добавил в свой файл макета:

= javascript_pack_tag 'stuff'

И еще попробовал добавить в pipelines application.js

//= require stuff
//= require_tree .

stuff.js был правильно скомпилирован в public / packs / stuff.js и находится в 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" 
}

Я также добавил это в инициализатор Assests.rb:

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

Я уверен, что мне не хватает чего-то маленького, и я слишком долго смотрел на это, чтобы увидеть это.

----- ОБНОВЛЕНИЕ -----

В исходном посте есть небольшой шум, так как я мучился, пытаясь заставить материал работать. В конце концов, вам просто нужна подсказка, предоставленная принятым ответом.

В app / javascript / packs / application.js добавьте:

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

И убедитесь, что в вашем макете есть:

= javascript_pack_tag 'application'

Мне не нужно было // = требовать что-то в конвейере application.js. Мне также не нужно было добавлять публичный каталог в инициализатор assets.rb.

Чтобы использовать в конвейерном js-файле, таком как users.js, просто убедитесь, что вы используете его после того, как все будет загружено следующим образом:

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

Или, если вы хотите встроить его в свой index.slim или что-то, что вы можете просто сделать:

javascript: 
   new Stuff();

После правильной настройки вы захотите перезапустить сервер webpack:

./bin/webpack-dev-server

Теперь, если вы внесете изменения в stuff.js, они должны быть скомпилированы и доступны сразу же, как и следовало ожидать.

Мой последний класс материала выглядит так:

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

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

person jacklin    schedule 21.06.2017    source источник


Ответы (1)


Вы должны объявить свой импортированный класс в window, чтобы использовать его в коде внешнего интерфейса (актив или в шаблоне). В свой пакет application.js добавьте следующее:

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

Тогда вы можете использовать это:

var foobar = new window.Stuff();

Пример полного стека здесь: https://gist.github.com/Aschen/f0a53b0d522688cc46ef77705074c1d2

person Aschen    schedule 21.06.2017
comment
Хм, а где бы я это положил? Я действительно не могу использовать импорт на стороне конвейера, потому что я не использую там babel или что-то еще. Я попытался добавить в application.js сторону webpacker, но это ничего не изменило. - person jacklin; 21.06.2017
comment
Извините, я не понял, вы должны добавить эти строки на стороне webpacker, в свой пакет application.js (я обновил свой ответ) - person Aschen; 21.06.2017
comment
Спасибо за вашу помощь! Однако я все еще получаю ReferenceError. Я перекомпилировал веб-упаковщик, перезапустил сервер и т. Д. New Stuff (); в моем users.js, похоже, все еще недоступен. - person jacklin; 21.06.2017
comment
Попробуйте var foobar = new window.Stuff - person Aschen; 21.06.2017
comment
Думаю, прогресс. Это дает ошибку: Uncaught TypeError: window.Stuff не является конструктором - person jacklin; 21.06.2017
comment
Хорошо, я понял! (Но я не знаю, почему он так себя ведет) В users.js вы должны использовать следующий синтаксис: var foobar = new window.Stuff(), но в консоли браузера вы можете использовать тот, который вам нужен. - person Aschen; 21.06.2017
comment
Хм ... так что это не сработало, но я видел, что new Stuff () действительно работает в консоли браузера. Я заметил, что если я изменю свой класс на window.Stuff = class Stuff {}, то он будет доступен в users.js. - person jacklin; 21.06.2017
comment
Вы запускали ./bin/webpack-dev-server? - person Aschen; 21.06.2017
comment
Ага. Похоже, единственное, что работает, - это поместить window.Stuff = class Stuff {} в файл stuff.js. Какой способ, я не уверен, лучший? - person jacklin; 21.06.2017
comment
По-видимому, вы можете использовать класс из веб-пакета другого класса, определенного в конвейере ресурсов. Вы также можете использовать класс webpack прямо в вашем представлении, используя встроенный javascript. Я провел несколько тестов, вы можете увидеть их здесь: gist.github.com/Aschen/f0a53b0d522688c46ef27074 / а> - person Aschen; 21.06.2017
comment
Большое спасибо за примеры! У меня сейчас работает. Если он находится в users.js, мне нужно было добавить $ (document) .on ('turbolinks: load', function () {new Stuff ();}), но в index.slim этого делать не нужно. Думаю, порядок загрузки вас спасет. Спасибо за вашу помощь! - person jacklin; 21.06.2017