Мы хотим обновить версию Ember, используемую в Discourse.
В настоящее время мы используем 3.15, и мы хотели бы перейти на 4.1.
Мы поставили цель завершить эту работу к концу года. Обратите внимание, что эта тема является дорожной картой, и все планы и оценки носят предварительный характер. Эта тема не предназначена для проведения значительных обсуждений конкретных обновлений или изменений. Поэтому давайте сосредоточимся на разговоре здесь. Вопросы о том, как эти обновления повлияют на ваш сайт/плагин/тему, не относятся к теме. Запланированные изменения на 100% касаются фронтенда (приложение Ember).
Мы будем очень осторожны с изменениями, которые мы вносим. Все официальные плагины/темы будут обновлены (включая любые пользовательские работы, выполненные CDCK для своих клиентов). Мы также отправим PR для обновления всех популярных неофициальных плагинов/тем.
Не беспокойтесь, если у вас есть пользовательский плагин/тема, который вы создали для своего сайта. Мы добавим предупреждения о устаревании и своевременно создадим необходимые объявления, чтобы дать вам достаточно времени для внесения необходимых изменений. Мы также постараемся помочь вам в этих изменениях, если это необходимо.
Начнем с целей. Мы, очевидно, хотим перейти на самую высокую доступную версию, но нам нужно установить промежуточные цели между настоящим моментом и нашей конечной целью.
Мы планируем выполнять инкрементные обновления. Вместо одного крупного обновления до 4.1, мы разобьем эту работу на шесть этапов. Каждый этап фокусируется на одном обновлении Ember.
| Этап | Размер | Обновления |
|---|---|---|
| 1 | size-l | Ember 3.15 → Ember 3.16 |
| 2 | size-m | Ember 3.16 → Ember 3.25 |
| 3 | size-xl | Ember 3.25 → Ember 3.26 (Часть 1 - Общее) Ember 3.25 → Ember 3.26 (Часть 2 - Шаблоны) Ember 3.25 → Ember 3.26 (Часть 3 - jQuery) Ember 3.25 → Ember 3.26 (Часть 4 - Подготовка к Octane) Ember 3.25 → Ember 3.26 (Часть 5 - Octane) |
| 4 | size-l | Ember 3.26 → Ember 3.27 (Часть 1 - Общее) Ember 3.26 → Ember 3.27 (Часть 2 - RenderTemplate) Ember 3.26 → Ember 3.27 (Часть 3 - Наследственные встроенные компоненты) |
| 5 | size-s | Ember 3.27 → Ember 3.28 |
| 6 | size-s | Ember 3.28 → Ember 4.1 |
Выбор этих конкретных версий полностью основан на устареваниях и объеме работы, которую они вводят, а также на подразумеваемом риске.
Итак, давайте разберем их более подробно для большей ясности.
Устаревания по обновлению
Этап 1 (size-l)
Ember 3.15 → Ember 3.16
Это обновление вводит только одно устаревание.
-
Использовать резольвер ember-CLI вместо наследственного глобального резольвера
- до: 4.0.0 - size-lDiscourse имеет свой собственный пользовательский резольвер, который в настоящее время расширяет
Ember.DefaultResolver.Рекомендуемое исправление — отказаться от любых пользовательских резольверов и использовать резольвер Ember-CLI resolver. Это легче сказать, чем сделать, потому что у нас есть довольно много пользовательской логики для обработки плагинов и тем.
Компромисс, который работает, — это расширение резольвера Ember-CLI вместо расширения
Ember.DefaultResolver.
Этап 2 (size-m)
Ember 3.16 → Ember 3.25
Это обновление вводит восемь устареваний.
-
Использовать геттер Ember и явно проверять на undefined
- до: 4.0.0 - size-sЭто простое устаревание. Нам нужно только удалитьgetWithDefaultв нашей кодовой базе, и есть всего несколько мест, где мы его используем. -
Расширения прототипа String
- до: 4.0.0 - size-mЭто также простая и низкорисковая замена, но мы используем расширенный прототип строки Ember в довольно многих местах. При быстром проверке я думаю, что у нас есть около < 100 мест, где мы это делаем между ядром и плагинами/темами.После обновления этих мест мы также должны предотвратить расширение этого прототипа Ember с помощью чего-то вроде этого.EXTEND_PROTOTYPES: { String: false }в нашем файле environment.
-
ИмпортhtmlSafeиisHTMLSafeиз @ember/string
- до: 4.0.0 - size-mЗдесь много пересечений с #7 в этом обновлении, и это должно быть прямолинейным и низкорисковым.
Этап 3 (size-xl)
Обновление с 3.25 до 3.26 довольно сложное. Здесь мы делаем большую часть “догоняющей” работы. Всего есть шестнадцать устареваний. Мы разобьем это обновление на пять частей — где мы делаем только повышение версии после того, как все устаревания будут обработаны.
Ember 3.25 → Ember 3.26 (Часть 1 - Общее)
Эта часть касается девяти устареваний, которые относительно легче обработать.
-
Методы перехода маршрутов и контроллеров
- до: 5.0.0 - size-mЭто устаревание удаляет несколько методов из
routesиcontrollers. Может показаться, что это сложное изменение, но оно должно быть прямолинейным. Нам нужно будет только внедритьRouterкак сервис и вызывать их оттуда, когда это необходимо. Трудная часть заключается в том, что мы используем их во многих местах, и все они должны быть обновлены. -
Политика поддержки браузеров
- до: 4.0.0 - size-s~~Это должно быть относительно простым изменением. Ember не будет поддерживать IE11 начиная с 4.0. Хорошая вещь здесь в том, что мы давно не поддерживаем его. Единственное, что нам нужно изменить, — это перестать транслировать для IE11 в продакшене.
discourse/app/assets/javascripts/discourse/config/targets.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHubЯ провел некоторые базовые тесты, и это изменение сэкономит нам около 60kb (gzip) или ~6% наших основных и вендорных бандлов в продакшене Ember-CLI. -
{{hasBlock}} и {{hasBlockParams}}
- до: 4.0.0 - size-sМы используем их в нескольких местах. Это простое, низкорисковое переименование. -
Хелпер{{with}}
- до: 4.0.0 - size-sМы редко используем это, но это все равно нужно исправить. Нам просто нужно заменить их и использовать{{let}}или комбинацию{{if}}/{{else}}
Ember 3.25 → Ember 3.26 (Часть 2 - Шаблоны)
Эта часть будет в основном фокусироваться на устареваниях, связанных с шаблонами .hbs. Есть три устаревания, на которых нам нужно сосредоточиться здесь.
-
Поиск свойства по умолчанию
- до: 4.0.0 - size-lНачиная с Ember 4.0, это больше не будет работать.
Hello, {{name}}!Если у нас есть свойство в шаблоне, мы должны искать его с предшествующим
this, вот такHello, {{this.name}}!Мы должны сделать это со всеми нашими шаблонами. Есть способы уменьшить боль здесь. Мы можем попробовать ember-no-implicit-this-codemod и посмотреть, насколько далеко это нас заведет.
Я за ограничение изменений до 1 файла на PR. Это облегчает обзор — и отмену, если что-то пойдет не так.
-
Доступ к именованным аргументам через {{attrs}}
- до: 4.0.0 size-xlОбъект
{{attrs}}будет удален в Ember 4.0. Само изменение очень прямолинейное, и пример Ember довольно хорош.До:
{{attrs.foo}} {{this.attrs.foo.bar}} {{deeply (nested attrs.foobar.baz)}}После:
{{@foo}} {{@foo.bar}} {{deeply (nested @foobar.baz)}}Мы должны сделать это для всех наших шаблонов. Мы можем объединить это изменение с конвертацией шаблонов в синтаксис с угловыми скобками. Я большой фанат угловых скобок, потому что они гораздо ближе к стандартному синтаксису пользовательских веб-компонентов.
Одна вещь, которая может ускорить наш прогресс здесь, — это ember-angle-brackets-codemod. Нам придется поэкспериментировать с ним и посмотреть, насколько далеко это нас заведет. Он обрабатывает устаревание и дает нам блестящий синтаксис с угловыми скобками.
Подобно #1 в этой части, я также предпочитаю исправлять и тестировать один шаблон на PR.
-
Позиционные аргументы
<LinkTo>
- до: 4.0.0 - size-mЭто также устаревание, направленное на уменьшение путаницы. Есть несколько мест, где мы используем позиционные аргументы в link-to. Мы можем исправить их вот так
До:
{{link-to "About Us" "about"}} {{#link-to "about"}}About Us{{/link-to}} {{#link-to "post" @post}}Read {{@post.title}}...{{/link-to}}После (с угловыми скобками):
<LinkTo @route="about">About Us</LinkTo> <LinkTo @route="about">About Us</LinkTo> <LinkTo @route="post" @model={{@post}}>Read {{@post.title}}...</LinkTo>
Ember 3.25 → Ember 3.26 (Часть 3 - jQuery)
Не могу сказать здесь ничего, чего вы уже не знали. Новые приложения Ember не используют jQuery, и он будет удален в Ember 4.0.
В этой части мы сосредоточимся на одном устаревании.
-
Опциональная функция: jquery-integration
- до: 4.0.0 - size-xlЗа последние пару лет мы сделали огромный прогресс в сокращении использования jQuery. Есть еще места, где нам это нужно, особенно в композере и как зависимость для некоторых вендорных библиотек, которые мы используем. Я не хочу вдаваться в детали этого изменения здесь. Длинная история коротка: мы должны уйти от использования jQuery.
Однако я хотел бы подчеркнуть, что даже если мы избавимся от jQuery ВЕЗДЕ, мы все равно должны оставить эту опцию установленной в true, пока мы не будем готовы к Ember 4.0. Нам нужен план, чтобы облегчить переход для сайтов с пользовательскими темами/плагинами, которыми мы не управляем. Другими словами, давайте сделаем работу, но будем жить с предупреждением об устаревании относительно выключения этой опции.
Ember 3.25 → Ember 3.26 (Часть 4 - Подготовка к Octane)
В этой части мы должны сосредоточиться на подготовке наших файлов к Octane. Мы обработаем два устаревания.
-
Опциональная функция: template-only-glimmer-components
- до: 4.0.0 - size-mЭто простое изменение в теории, но есть подразумеваемая работа, которую нам нужно сделать, прежде чем мы сможем переключить эту опцию.
Нам нужно убедиться, что наши текущие шаблонные компоненты работают с семантикой glimmer. Я провел некоторые тесты, и наши тесты задушили с этой опцией, включенной. Вот примерный список некоторых шаблонных компонентов, которые у нас есть в ядре
- app/templates/components/activation-email-form.hbs - app/templates/components/cancel-link.hbs - app/templates/components/categories-with-featured-topics.hbs - app/templates/components/category-name-fields.hbs - app/templates/components/color-input.hbs - app/templates/components/custom-html-container.hbs - app/templates/components/emoji-group-buttons.hbs - app/templates/components/emoji-group-sections.hbs - app/templates/components/empty-state.hbs - app/templates/components/ip-lookup.hbs - app/templates/components/modal-footer-close.hbs - app/templates/components/popup-menu.hbs - app/templates/components/reviewable-created-by-name.hbs - app/templates/components/reviewable-created-by.hbs - app/templates/components/reviewable-field-editor.hbs - app/templates/components/reviewable-field-text.hbs - app/templates/components/reviewable-field-textarea.hbs - app/templates/components/reviewable-field.hbs - app/templates/components/reviewable-flagged-post.hbs - app/templates/components/reviewable-post-header.hbs - app/templates/components/reviewable-post.hbs - app/templates/components/reviewable-scores.hbs - app/templates/components/reviewable-tags.hbs - app/templates/components/reviewable-topic-link.hbs - app/templates/components/score-value.hbs - app/templates/components/selected-posts.hbs - app/templates/components/subcategories-with-featured-topics.hbs - app/templates/components/text-overflow.hbs - app/templates/components/user-fields/confirm.hbs - app/templates/components/user-fields/dropdown.hbs - app/templates/components/user-fields/multiselect.hbs - app/templates/components/user-fields/text.hbs - app/templates/components/user-profile-avatar.hbs - app/templates/components/user-summary-users-list.hbsНам также нужно будет проверить наши шаблоны Admin/темы/плагина и убедиться, что все работает, прежде чем отправлять эту опцию.
На ходу я не совсем уверен, как наши сырые
.hbrшаблоны впишутся в это. Однако, @david работал над списками тем на основе glimmer. Так что, может быть, мы сможем полностью отказаться от сырых шаблонов. -
Неявные внедрения
- до: 4.0.0 size-xlМы используем неявные внедрения повсюду. Мы делаем это в инициализаторе вот так
discourse/app/assets/javascripts/discourse/app/pre-initializers/inject-discourse-objects.js at ac79c5efc61d259705eeb487ca21d0ec3c535807 · discourse/discourse · GitHubEmber уходит от неявных внедрений. Предпочтительный путь вперед — это конвертировать как можно больше наших объектов в сервисы и явно внедрять их там, где они нужны. Конечно, может быть несколько вещей, где сервис не идеален. В этих случаях мы можем искать эти объекты напрямую, когда они нужны, вот так
getOwner(this).lookup('thing:main')Другой вариант, который у нас есть (в зависимости от последствий для производительности), — это обернуть классы Ember нашим собственным классом Discourse. Мы будем использовать наш класс по всему приложению. Подобно тому, как мы делаем с
GlimmerComponent Class
discourse/app/assets/javascripts/discourse/app/components/glimmer.js at fa0c796baf9a7f64a3b27823b1aa4b370a74c3eb · discourse/discourse · GitHub. Это сделает эту задачу size-l или даже size-mВ любом случае, это изменение потребует некоторых размышлений.
Ember 3.25 → Ember 3.26 (Часть 5 - Octane)
Это последний рывок обновления 3.25 → Ember 3.26. У нас останется только одно устаревание на этом этапе, но оно большое.
-
Эдиция: Classic
- до: 4.0.0 - size-xlПеред тем как переключить нашу версию на Octane, я хотел бы потратить время на конвертацию наших классов в нативные классы и наши компоненты в компоненты Glimmer. Будет немного боли, но оно того стоит. ember-native-class-codemod должен облегчить часть этой боли. Нам придется посмотреть, насколько далеко это нас заведет.
Есть много соображений и проблем с рабочим процессом, о которых нужно помнить. Единственное, что я хочу подчеркнуть, — это то, что это будет следовать тому же потоку, который я упомянул для шаблонов — исправлять и тестировать 1 компонент на PR.
Этап 4
Обновление Ember 3.26 → Ember 3.27 вводит двенадцать устареваний. Я предлагаю разделить их на три части. Мы сделаем повышение версии после того, как все устаревания будут обработаны.
Ember 3.26 → Ember 3.27 (часть 1 - Общее)
-
Устаревание
Route#disconnectOutlet
- до: 4.0.0 - size-sМы делаем это только в одном месте. Это
build-category-route, и его должно быть легко исправить. -
Вызов хелперов без аргументов и скобок в позициях именованных аргументов
- до: 4.0.0 - size-sЯ не думаю, что мы делаем это где-либо, но я подтвержу, когда придет время. По сути, вызов хелпера без передачи ему каких-либо аргументов.
Даже если мы используем что-то подобное, нам нужно будет только добавить скобки. Так что это
<SomeComponent @arg={{someHelper}} />становится
<SomeComponent @arg={{(someHelper)}} />обратите внимание на скобки вокруг
someHelper -
Доступ к точкам в цикле выполнения и вычисляемых свойствах
- до: 4.0.0 - size-mМы используем
.для доступа к функциямcomputedв нашем аддонеdecorators. Они выглядят так, например
discourse/app/assets/javascripts/discourse-common/addon/utils/decorators.js at b05fddaa7ce3968ffc70cd8d4bf290e15d06eb11 · discourse/discourse · GitHubУ нас также есть несколько разовых случаев здесь и там. Насколько я могу судить, исправление этих мест в основном связано с исправлением того, как мы их импортируем.
Так что
computed.filterдолжен быть импортирован вот так.import { filter } from '@ember/object/computed';Наша версия внешнего вендорного аддона
buffered-proxyиспользует.для доступа к функциямcomputed; нам нужно будет повысить его.Мы также используем
.для доступа к функциямrunв нескольких местах. Тем не менее, применяется то же исправление. Нам нужно обновить способ их импорта. Я думаю, что темы и плагины особенно могут иметь довольно много мест, где мы делаем это сrun -
Устаревание глобального Ember
- до: 4.0.0 - (#size ?)Emberне будет доступен в глобальном контексте после 4.0. Трудно оценить объем работы/влияния здесь без более глубокого взгляда. Тем не менее, я знаю, что @cvx делал тонну работы, чтобы избавиться от этого паттерна.
Ember 3.26 → Ember 3.27 (часть 2 - renderTemplate)
Эта часть будет фокусироваться только на одном устаревании.
-
Устаревание
Route#renderTemplate
- до: 4.0.0 - size-lВ двух словах, мы не можем использовать именованные outlets в Ember 4.0. Так что это не будет работать.
{{outlet "thing"}}Мы используем
renderTemplateпочти в 30 местах только в ядре. Само обновление кажется довольно прямолинейным. Мы можем использовать{{#in-element}}и пустой HTML-элемент как заглушку для того, что мы раньше рендерили в именованных outlets.
Ember 3.26 → Ember 3.27 (часть 3 - Наследственные встроенные компоненты)
Эта часть будет фокусироваться на встроенных наследственных компонентах, и она обработает четыре устаревания.
- Импорт наследственных встроенных компонентов
- до: 4.0.0 - Наследственные аргументы встроенных компонентов
- до: 4.0.0 - Наследственные аргументы атрибутов HTML встроенных компонентов
- до: 4.0.0 - Повторное открытие наследственных встроенных компонентов
- до: 4.0.0
Я не добавил размеры к этим, потому что… это действительно зависит. Позвольте мне объяснить.
Наследственные встроенные компоненты, такие как Checkbox, TextField, TextArea и LinkComponent, будут удалены в Ember 4.0. Мы используем их в довольно многих местах, и мы также используем некоторые устаревшие паттерны на них.
Ember предлагает путь обновления, который позволяет нам продолжать их использовать, но мы должны импортировать их по-другому. Однако они не будут получать никаких обновлений от Ember и останутся замороженными. Я надеюсь, что мы сможем избавиться от всех них; однако, это может быть немного сложным. Это изменение потребует большего обсуждения, когда придет время.
Этап 5
Ember 3.27 → Ember 3.28
Это size-s, поскольку это только повышение версии. 3.28 — последний LTS релиз в цикле разработки 3.x. Он не вводит никаких новых устареваний после 3.27, и это хорошая версия, на которой мы можем остановиться на несколько недель, пока все не успокоится.
3.28 LTS поддерживается до августа 2022 года (как исправления ошибок, так и патчи безопасности)
Этот “перерыв” имеет несколько преимуществ.
- Это дает нам больше времени, чтобы увидеть, возникнут ли какие-либо проблемы
- когда мы отправим стабильную версию, она должна быть на 3.28
- это дает нам время, чтобы сделать любые объявления, которые нам нужно сделать относительно самостоятельно поддерживаемых тем и плагинов
- это дает нам время, чтобы убедиться, что переход от jQuery к no jQuery будет максимально плавным.
Этап 6
После того как пройдет несколько недель, мы наконец сможем повысить нашу версию до Ember 4
Ember 3.28 → Ember 4.1
Теперь мы можем выключить опциональную интеграцию jQuery как последнее устаревание из цикла 3.x.
Это обновление вводит два незначительных устаревания.
-
Устаревание Ember.assign
- до: 5.0.0 - size-sМы не используем это в ядре, но нам нужно будет проверить темы/плагины. В любом случае, это простое переименование. -
Класс AutoLocation
- до: 5.0.0 - size-sВ теории, нам нужно будет только изменить
locationType: 'auto'наlocationType: 'history'в нашем файле среды Ember, и это должно просто работать.
Рабочий процесс
Как я упоминал в начале, мы будем очень осторожны с этими обновлениями. Мы будем тестировать/исправлять/фиксировать все официальные плагины/темы с каждым обновлением, и мы также отправим PR для популярных неофициальных плагинов/тем.
Цель здесь не замедлять разработку или создавать головную боль. Так что PR должны быть строго ограничены, с одним изменением на PR и ничего слишком большого.
В идеальном мире все изменения происходили бы на заднем плане, не прерывая работу других. Вот почему мы планируем держать PR короткими и сладкими. Также, мы не слишком любим смешанные паттерны. Так что мы не хотим застрять в промежуточном состоянии на уровне файлов. Компонент либо классический, либо Glimmer, и шаблон либо использует фигурные скобки, либо угловые скобки, ничего между ними.
Я надеюсь, что эта дорожная карта была ясной. Как я упоминал в начале, это просто общий обзор верхнего уровня. Если что-то неясно, неверно или не нравится вам, пожалуйста, дайте нам знать.