Загрузка JS-библиотек через register_asset

Я заметил, что JS-файлы, добавляемые через register_asset с помощью плагинов, передаются в функцию eval в виде строки.

Проблема с eval заключается в том, что он не добавляет объект в глобальную область видимости, как обсуждалось здесь: https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope. Это критически важно для использования JS-библиотек.

Если быть конкретнее, я пытался использовать https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js в плагине, но функции были недоступны в файлах Ember.

Обходной путь заключается в обработке файла через webpack с использованием параметра libraryTarget со значением umd.

Многие библиотеки обрабатываются именно так, и это, как правило, работает «из коробки».

Я не эксперт в этих вопросах, но просто задаюсь вопросом: имеет ли смысл для Discourse добавлять зарегистрированные ассеты в глобальную область видимости?

Примечание: Извините, если это звучит глупо. Я не ожидал, что мне придётся возиться с webpack, чтобы заставить JS-библиотеки работать с Discourse, но именно это и побудило меня написать этот пост. :wink:

Что-то здесь не так — я посмотрел на наш плагин lazyYT, который подключает ассет через register_asset, и он не находится в блоке eval.

Можете привести небольшой пример плагина, воспроизводящего проблему?

Интересно, не является ли это непреднамеренным побочным эффектом

(т. е. это происходит только в режиме разработки)

Я тоже об этом думал — если это так, то есть обходные пути, но мне нужен воспроизводимый пример.

Конечно.

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

@eviltrout

Маленький плагин, использующий ту же библиотеку, о которой упоминалось в первом посте: GitHub - fzngagan/js-test · GitHub

Я просто попытался вызвать функцию, добавленную этой библиотекой, в инициализаторе, но в консоли JS получаю ошибку: ReferenceError: RecordRTC is not defined.

Я использовал неминифицированную версию библиотеки, что может помочь в отладке.

Также скриншот из вкладки sources, показывающий, что весь код был передан в функцию eval.

Ещё одно наблюдение: включённые JS-файлы в discourse-spoiler-alert и lazy-yt внедряют функции в глобальный объект jQuery, но не объявляют никаких функций верхнего уровня.

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

Мое предложение — переупаковать JS с поддержкой UMD, а затем импортировать его, но это может быть сложно настроить, если у вас нет большого опыта работы с модулями JS.

Вместо этого простой способ заставить это работать — отредактировать RecordRTC.js и добавить следующую строку:

window.RecordRTC = RecordRTC;

Еще лучше обернуть всё содержимое в IIFE:

(function(exports) {
  // здесь располагается исходное содержимое файла
  exports.RecordRTC = RecordRTC;
})(window);

Да, я согласен. Многие из них распространяются именно так, и они работают безупречно. Спасибо, что разобрались в этом и подтвердили :+1: Я пошёл по пути упаковки библиотеки через webpack, и она работает даже без явного импорта. Хотя мне следовало протестировать это в режиме production.