Ассеты JavaScript в компоненте темы

Я пытаюсь создать компонент темы для предварительного просмотра STL-файлов. Для этого есть отличная библиотека JavaScript, но я не уверен, как заставить её работать внутри компонента темы.

Это обычный JavaScript, не ES6, и, как я полагаю, это означает, что я не могу просто поместить его в директорию «javascripts» и импортировать, верно? Кроме того, библиотека, похоже, полагается на импорт через тег .

Таким образом, я могу создать тег и добавить его в заголовок документа, но как мне найти имя файла JS библиотеки? Также библиотека состоит из нескольких JS-файлов, и она предполагает, что эти файлы будут доступны в одной и той же директории. Далее она создаёт дополнительные теги для загрузки остальной части библиотеки.

Так, должны ли эти файлы находиться в директории «javascripts»? Или их следует рассматривать как ассеты? Ближайшее, что я могу найти для выполнения подобной задачи, — это плагин discourse-math, но, если возможно, я бы предпочел оставить это в виде компонента темы.

Похоже, здесь показано, как это сделать для плагина: How to ship javascript library with plugin?
Пока ничего не нашёл для компонента темы.

Не знаю, но у тебя нет хороших ответов!

Следующее, на что стоит обратить внимание, — это… эээ… включение других файлов в компонент темы.

Думаю, стоит посмотреть на крупные компоненты тем. В общем, я считаю, что структура файлов в компоненте темы такая же, и Ember просто загрузит эти файлы темы так же, как и плагины.

Я так не думаю, каждый компонент получает свою собственную виртуальную директорию, насколько я знаю. Что-то вроде discourse/theme-10/… Поэтому, чтобы загрузить оттуда что-то, я должен хотя бы каким-то образом знать, как называется эта директория.

Похоже, имена ассетов доступны только как переменные, а реальные имена представляют собой длинные и сложные числа, так что этот вариант тоже не подойдёт.
Кажется, что сейчас нет способа реализовать это в виде компонента, поэтому я пока буду загружать JS-файлы через nginx и получать к ним доступ таким образом. Вероятно, это означает, что этот компонент, к сожалению, будет работать только у меня.

Вы можете добавить обычный тег скрипта в файл header.html внутри компонента вашей темы.

Сайдлоадинг работает!
Только один раз. :frowning:

Если я перейду к другой теме и вернусь к теме со STL-файлом, он перестает работать. Я не знаю почему, потому что в консоли JavaScript нет ошибок. Ранее я видел где-то обсуждение, где говорилось о странностях с onload, и учитывая, что эти скрипты используют onload, возможно, это связано?

Верно, но код viewstl не предназначен для встраивания.
При подгрузке с боковой панели я добавил тег script в common/head_tag.html следующим образом:

<script src="/xi/viewstl/stl_viewer.min.js"></script>

(путь /xi/ обслуживается через nginx)

Discourse — это SPA. Просто добавить скрипт с обработчиком onLoad не получится, это не сработает. Вам нужно подключиться к нашим API-эндпоинтам. Ознакомьтесь с Руководством разработчика по темам Discourse

Ладно, тогда я попробую заменить устаревшую загрузку через теги script на что-то другое.

Я уже несколько раз прочитал эту страницу, но всё ещё не могу заставить это работать.
Я пытаюсь загрузить three.js с помощью операторов import, но, кажется, что бы я ни делал, система жалуется, что не может найти импорт. Странно то, что другие файлы импортируются без проблем, а сообщение об ошибке совершенно не помогает.

В любом случае, вот что я получаю, возможно, кто-то сможет помочь:

Вот импорт, который не работает:

А вот ошибка, которую я получаю:

_application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74333 Произошла ошибка в теме/компоненте "STL previews": Error: Could not find module `discourse/theme-17/three/build/three.module` imported from `discourse/theme-17/stlviewer/StlViewer`
    at h (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74612)
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74581
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74665
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74490
    at require (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74663)
    at h (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74616)
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74581
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74665
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74490
    at require (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74663)
(anonymous) @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74333
u @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74325
initialize @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74304
i.initialize @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:7723
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49335
e.each @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67724
e.walk @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67638
e.each @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67568
e.topsort @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67576
_runInitializer @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49361
runInitializers @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49333
_bootSync @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:47768
domReady @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:47668
n._run @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67275
n._join @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67251
n.join @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:66968
f @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:53760
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:53864
l @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3776
c @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3844
setTimeout (async)
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3882
u @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3510
fireWith @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3640
fire @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3648
u @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3510
fireWith @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3640
ready @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:4120
z @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:4130

Является ли «.» магическим разделителем модулей или чем-то подобным?

Кажется, точка ‘.’ играет особую роль, потому что при переименовании three.module.js в three_module.js возникает совершенно другая проблема: тема больше не загружается (ошибка 500).

Я также пробовал импортировать three.js напрямую с CDN по полному URL, но это тоже, похоже, не работает…

Если вам просто нужна отложенная загрузка (Just In Time) JavaScript-ресурса, как в моём случае, где требуется библиотека D3, вы можете использовать этот паттерн с Loadscript:

и выше по коду:

Loadscript возвращает Promise, поэтому к результату необходимо применить .then. (Я не уверен, но предполагаю, что результат кэшируется неявно, поэтому при повторном запуске он будет выполняться быстрее и т. д.)

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

Обратите внимание, что код выполняется внутри компонента Ember и вызывается в хуке didInsertElement. Подробнее о компонентах Ember читайте здесь: Templates are HTML - Components - Ember Guides

Также обратите внимание, что сами скрипты находятся в директории javascripts/assets.

Я основал это на коде от @j.jaffeux, который использовался для загрузки совершенно другого скрипта (спасибо Жоффре! :+1: )

Вот пример для Discourse:

Совет: всегда заглядывайте в официальные и Pavilion TC, а также в плагины, которые делают что-то подобное, чтобы увидеть, как они реализуют подобные вещи :).

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

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