Как включить загрузчик с помощью scalajs-bundler - PullRequest
0 голосов
/ 25 апреля 2019

Я использую плагин scalajs-bundler и определил мой build.sbt следующим образом:

enablePlugins(ScalaJSBundlerPlugin)

name := "Reproduce"
scalaVersion := "2.12.8"

npmDependencies in Compile += "bootstrap" -> "3.4.1"

Однако, когда я запускаю "sbt fastOptJS :: webpack", в файле -fastopt-bundle.js, который генерируется, нет ссылки на начальную загрузку.

Разве нельзя включить загрузчик?

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Я просто столкнулся с точно такой же проблемой и не смог найти решение ни в одном поиске.Надеюсь, что этот (довольно длинный) ответ поможет другим избежать некоторой боли.

Я думаю, что есть 3 проблемы, которые нужно решить, чтобы использовать библиотеку Bootstrap, входящую в состав модуля npm (т.е. использовать scalajs-bundler для ее упаковки).через параметр npmDependencies).

1) Загрузите библиотеку начальной загрузки в пакет.
2) Сделайте символ jQuery доступным для Bootstrap в качестве глобальной переменной.
3) Загрузите Bootstrap во время выполнения,

1) Получение модулей в комплекте

Это первая проблема, о которой вы упоминаете в своем вопросе.Добавление bootstrap к npmDependencies недостаточно для того, чтобы заставить scalajs-bundler включить ваш модуль в комплект.Кроме того, где-то в вашем коде scala у вас должен быть оператор JSImport ("имя_библиотеки", ...).Это говорит scalajs-bundler, что вы на самом деле используете библиотеку и что ее нужно включить в комплект.Подробнее о JSImport вы можете прочитать здесь .Я нашел это описание немного расплывчатым. Здесь - это ответ на мой вопрос от @Julien Richard-Foy, который мне показался гораздо более полезным.В моем коде соблюдено требование JSImport, включенное в часть 3 ниже.Обратите внимание, вам также понадобится JSImport для библиотеки jquery, чтобы убедиться, что он также включен в комплект, поскольку Bootstrap зависит от него, и вам необходимо добавить jquery в npmDependencies.

2) Создание глобальных переменных javascript

Это самая сложная часть решения.

В моем приложении я получаю сообщение об ошибке в консоли браузера, например jQuery is not defined.Мне потребовалось некоторое время, чтобы определить, что это было вызвано внутри библиотеки Bootstrap.Библиотека Bootstrap зависит от библиотеки jquery, предполагая, что глобальная переменная jQuery определена.К сожалению, простого включения jquery в комплект через npmDependencies и JSImport недостаточно.Вы должны указать scalajs-bundler создать глобальную переменную jQuery и экспортировать ее во все модули вашего пакета.

Решение @Julien Richard-Foy, на которое указывает общий рецепт, которому нужно следовать, но я считаю, что это ошибка.Ошибка не вызывает проблемы в их примере , потому что имя библиотеки и имя глобальной переменной идентичны.Проблема в том, что modName и globalModules[modName] поменялись местами в строке возврата importRule.

Вот мой файл common.webpack.config.js для scalajs-bundler, который инструктирует его генерировать глобальную переменную jQuery и экспортируйте его.Обратите внимание, единственные изменения, которые я сделал, заключались в том, чтобы поместить jquery: "jQuery" в globalModules и поменять местами позиции modName и globalModules[modName] на обратной линии importRule.В противном случае я просто следовал примеру (т.е. требуются другие конфигурационные файлы и изменения для build.sbt).

var globalModules = {
  jquery: "jQuery"
};

const importRule = {
  // Force require global modules
  test: /.*-(fast|full)opt\.js$/,
  loader:
    "imports-loader?" +
    Object.keys(globalModules)
      .map(function(modName) {
        return globalModules[modName] + "=" + modName;
      })
      .join(",")
};

const exposeRules = Object.keys(globalModules).map(function(modName) {
  // Expose global modules
  return {
    test: require.resolve(modName),
    loader: "expose-loader?" + globalModules[modName]
  };
});

const allRules = exposeRules.concat(importRule);

module.exports = {
  performance: { hints: false },
  module: {
    rules: allRules
  }
};

Некоторые дополнительные ресурсы по работе import-loader и expose-loader .

3) Загрузка модулей во время выполнения

Обычно это не то, что вы должны делать явно.Однако в случае Bootstrap (или любой библиотеки js, которая расширяет другую библиотеку js), вы, вероятно, не будете вызывать библиотеку напрямую через фасад.Скорее всего, вы будете использовать шаблон Monkey Patching .В этом случае объект jQuery приводится к объекту Bootstrap без непосредственного вызова библиотеки Bootstrap.Обычно это скомпилируется просто отлично, но вы получите ошибку времени выполнения в консоли браузера, что-то вроде Uncaught TypeError: jq.modal is not a function.Вот как определяется расширение Bootstrap для jquery, чтобы вы могли иметь некоторое представление о jq и модальности в сообщении об ошибке:

  @js.native
  trait BootstrapJQuery extends JQuery {
    def modal(action: String): BootstrapJQuery = js.native
    def modal(options: js.Any): BootstrapJQuery = js.native
  }

  implicit def jq2bootstrap(jq: JQuery): BootstrapJQuery = jq.asInstanceOf[BootstrapJQuery]

Решение состоит в том, чтобы сделать некоторую явную ссылку на библиотеку за некоторое время до того, как неявное будетвызывается.

Вот как я это сделал.

  private object BootstrapLib {
    @js.native
    @JSImport("bootstrap", Namespace)
    object BootstrapModule extends js.Object

    private lazy val dummy = BootstrapModule

    def load() = dummy
  }
  BootstrapLib.load()

Он содержится внутри объекта, который содержит все определения оболочки для компонентов Bootstrap. Это гарантирует, что Bootstrap.load() будет вызван перед использованием любой из оболочек Bootstrap. Мне это нравится, так как не нужно помнить, чтобы вызывать его явно в любом из методов фабрики обертки.

0 голосов
/ 26 апреля 2019

Вы должны фактически использовать модуль, иначе веб-пакет не включит его в полученный пакет.Если ваш модуль следует использовать из глобального пространства имен, следуйте этому рецепту .

...