На следующей неделе я объединю этот PR, который позволяет темам и компонентам иметь тесты QUnit, но он также меняет способ обработки/транспилирования JavaScript тем в Discourse. Реализовать эти изменения обратно совместимым образом очень сложно без переработки значительной части кода ядра (что, в свою очередь, может привести к другим изменениям, нарушающим обратную совместимость), поэтому при обновлении вашего сайта JavaScript ваших тем/компонентов может перестать работать.
В этом посте я объясню, какие изменения могут повлиять на ваши темы/компоненты и что нужно сделать, чтобы исправить ситуацию.
1. JavaScript внутри тегов <script type="text/discourse-plugin"> будет выполняться с включенным строгом режиме
Это изменение не влияет на JS-код, который находится вне тегов <script type="text/discourse-plugin">. Если ваш код находится в обычных тегах <script> или в отдельных файлах .js, вы полностью защищены от этого изменения.
Самый простой способ проверить, затронут ли ваша тема или компонент этим изменением, — обернуть ваш JS-код в вызываемое сразу выражение функции (IIFE) и добавить "use strict"; в начало кода. Например, предположим, что сейчас ваш код темы выглядит так:
<script type="text/discourse-plugin" version="0.8.11">
a = 5;
console.log(a);
</script>
После обертки в IIFE он должен выглядеть так ("use strict"; важен, так как включает строгий режим, и мы хотим проверить, как ведет себя наш код в этом режиме):
<script type="text/discourse-plugin" version="0.8.11">
(function() {
"use strict";
a = 5;
console.log(a);
})();
</script>
Если после этого ваш компонент перестал работать, значит, при обновлении сайта он сломается. Чтобы исправить код, настоятельно рекомендую сначала ознакомиться с документацией MDN по строгому режиму JavaScript, а затем проверить, не делает ли ваша тема/компонент ничего запрещенного в строгом режиме. Если да, то нужно рефакторить код, чтобы исключить такие действия.
Самая вероятная ошибка, с которой вы столкнетесь, — это ReferenceError при объявлении переменной без ключевого слова var (или let/const). В примере выше строка a = 5; вызовет исключение ReferenceError в строгом режиме, так как мы забыли добавить var. Исправленный код выглядит так:
<script type="text/discourse-plugin" version="0.8.11">
(function() {
"use strict";
var a = 5;
console.log(a);
})();
</script>
После завершения тестирования/исправления кода вы можете смело удалить IIFE и строку "use strict";.
2. Пути к модулям JavaScript тем будут иметь префикс с ID темы.
Некоторое время назад мы добавили новую функцию, позволяющую разделять JavaScript тем на несколько файлов, и мне нужно дать немного контекста об этой функции, чтобы объяснить предстоящее изменение.
Когда тема или компонент, поставляемый с отдельными файлами JavaScript, устанавливается на экземпляр Discourse, система перебирает все файлы JavaScript и создает модуль для каждого из них. Каждый модуль должен иметь уникальный идентификатор (также известный как путь), поэтому Discourse использует путь к файлу (с небольшими изменениями) в качестве пути модуля.
Например, если ваша тема/компонент имеет файл по адресу javascripts/discourse/helpers/my-helper.js, Discourse создаст модуль для этого файла и назначит ему путь discourse/helpers/my-helper. Этот модуль будет содержать транспилированную версию JavaScript из исходного файла.
Преимущество модулей в том, что вы можете импортировать классы/функции/объекты и т. д. из одного модуля в другой. Например, вы можете импортировать функцию xyz из my-helper в другие модули, используя оператор import следующим образом:
// javascripts/discourse/controllers/my-theme-controller.js
import { xyz } from "discourse/helpers/my-helper";
PR, который я объединю на следующей неделе, добавит префикс к путям модулей тем. Таким образом, в нашем примере my-helper изменится с discourse/helpers/my-helper на discourse/theme-<theme_id>/helpers/my-helper. Это означает, что наш оператор import перестанет работать, так как путь к модулю изменится. Чтобы исправить это, нужно просто изменить путь в операторе import с абсолютного на относительный, как показано ниже:
// javascripts/discourse/controllers/my-theme-controller.js
import { xyz } from "../helpers/my-helper";
Теперь наш оператор import должен работать снова. Посмотрите эти PR 1 и 2 для реальных примеров компонентов, затронутых пунктом (2), и того, как они были исправлены.
Еще раз: это влияет на вашу тему/компонент только в том случае, если он импортирует из одного из своих собственных модулей; импорт модулей ядра не затрагивается этим изменением.
Надеюсь, это поможет. Если у вас возникнут вопросы, пожалуйста, дайте мне знать!