На прошлой неделе на Vue.js London я рассказал, что произойдет в следующей мажорной версии Vue. Этот пост содержит подробный обзор плана.
Почему новая мажорная версия?
Vue 2.0 был выпущен ровно два года назад (как время летит!). В течение этого времени ядро Vue оставалось обратно совместимым и получило 5 минорных релизов. Мы накопили ряд идей, которые приведут к улучшению, но они не были реализованы, потому что они приведут к поломке обратной совместимости. В то же время экосистема JavaScript и сам язык быстро развиваются. Есть усовершенствованные инструменты, которые могли бы улучшить рабочий процесс и множество новых языковых функций, которые могли бы облегчить более простые, более полные и более эффективные решения проблем, которые пытается решить Vue. Что еще более интересно, так это то, что мы видим, что поддержка ES2015 становится все лучше и лучше для основных браузеров.
Vue 3.0 нацелен на использование этих новых языковых функций, чтобы сделать ядро Vue меньше, быстрее и мощнее. Vue 3.0 в настоящее время находится в стадии прототипирования, и мы уже внедрили среду выполнения, близкую к версии 2.x. Многие из перечисленных ниже элементов либо уже реализованы, либо подтверждено, что это возможно. Пункты, которые еще не реализованы или еще находятся на стадии планирования, отмечены знаком (*).
Детали
Изменения API высшего уровня
TL;DR: Все, кроме API render функции и синтаксиса scoped slots, либо останется таким же, либо может быть совместимо с версией 2.x через сборку совместимости.
Поскольку это мажорная версия, некоторые изменения будут иметь место. Однако мы серьезно относимся к обратной совместимости, поэтому мы хотим как можно скорее опубликовать список этих изменений.
Вот текущие запланированные публичные изменения API:
- Синтаксис шаблонов останется на 99% прежним. Могут быть небольшие изменения в синтаксисе scoped slots, но кроме этого мы не планируем ничего менять для шаблонов.
- 3.0 будет поддерживать компоненты на основе классов изначально, с целью предоставления API, который приятно использовать в нативном ES2015, не требуя каких-либо средств транспиляции или stage-x функционала. Большинство текущих параметров будут иметь разумное сопоставление в API на основе классов. Функции Stage-x, такие как поля классов и декораторы, по-прежнему могут быть использованы дополнительно. Кроме того, API разработан с учетом TypeScript. Кодовая база 3.x сама будет написана на TypeScript и обеспечит улучшенную поддержку TypeScript. (Тем не менее, использование TypeScript в приложении по-прежнему полностью необязательно).
- Компоненты на основе объектов 2.x по-прежнему будет поддерживаться внутренним преобразованием объекта в соответствующий класс.
- Миксины по прежнему будут поддерживаться. *
- API верхнего уровня, скорее всего, получит изменения, чтобы избежать глобального вмешательства в прототип Vue при установке плагинов. Вместо этого плагины будут применены и привязаны к дереву компонентов. Это упростит проверку компонентов, которые зависят от определенных плагинов, а также позволит монтировать несколько приложений Vue на одной странице с разными плагинами, но используя ту же самую среду выполнения Vue. *
- Функциональные компоненты могут, наконец, быть простыми функциями — во всяком случае, асинхронные компоненты теперь должны быть явно созданы с помощью вспомогательной функции.
- Часть, которая получит наибольшее количество изменений — это Virtual DOM, используемый в функциях рендеринга. В настоящее время мы собираем отзывы от основных авторов библиотек и будем делиться более подробными сведениями, поскольку мы уверены в изменениях, но пока вы не сильно полагаетесь на самописные (не JSX) функции рендеринга в своем приложении, он должен быть достаточно простым процессом.
Архитектура исходного кода
TL;DR: улучшены отдельные внутренние модули, TypeScript и кодовая база, в которую легче внести свой вклад.
Мы переписываем Vue с нуля для более чистой и удобной архитектуры, в частности, пытаясь облегчить работу. Мы нарушаем некоторые внутренние функции в отдельных пакетах, чтобы изолировать объем сложности. Например, модуль наблюдателя станет его собственным пакетом, с его собственным публичным API и тестами. Обратите внимание, что это не влияет на API уровня фреймворка: вам не придется вручную импортировать отдельные модули из нескольких пакетов, чтобы использовать Vue. Вместо этого последний пакет Vue собирается с использованием этих внутренних пакетов.
Кодовая база также теперь написана на TypeScript. Несмотря на то, что это сделает знание TypeScript предварительным условием для внесения вклада в новую кодовую базу, мы считаем, что информация о типе и поддержка IDE на самом деле облегчат внесение значимого вклада для мэйнтейнера.
Разделение наблюдателя и планировщика на отдельные пакеты также позволяет легко экспериментировать с альтернативными реализациями этих частей. Например, мы можем реализовать паттерн наблюдателя, совместимый с IE11, с тем же API или альтернативным планировщиком, который использует requestIdleCallback
для вывода в браузер во время простоя. *
Механизм наблюдения
TL;DR: более полное, точное, эффективное и отлаживаемое отслеживание реактивности и API для создания наблюдаемых объектов.
Vue 3.0 будет поставляться с реализацией наблюдателя на основе Proxy, которая обеспечивает отслеживание реактивности. Это устраняет ряд ограничений текущей реализации Vue 2 на основе Object.defineProperty
:
- Обнаружение добавления/удаления свойств
- Обнаружение мутации индекса Array/.length
- Поддержка Map, Set, WeakMap и WeakSet
Новый наблюдатель также имеет следующие преимущества:
- Открытый API для создания наблюдаемых объектов. Это подразумевает простое решение для управления несколькими компонентами для небольших сценариев.
- Ленивое наблюдение по-умолчанию. В 2.x любые реактивные данные, независимо от того, насколько они велики, будут отслеживаться при запуске. Это может вызвать заметные накладные расходы при запуске приложения, если у вас большой набор реактивных данных. В 3.x необходимо будет отслеживать только те данные, которые используются для рендеринга изначально видимой части вашего приложения, не говоря уже о том, что само наблюдение также намного быстрее.
- Более точное уведомление об изменении. Пример: в 2.x принудительное добавление нового свойства с использованием
Vue.set
приведет к тому, что любой наблюдатель будет зависеть от объекта для переоценки. В 3.x будут уведомлены только наблюдатели, которые полагаются на это конкретное свойство. - Неизменяемые наблюдаемые объекты: мы можем создавать "неизменяемые" версии объекта, которое предотвращает мутации даже при вложенных свойствах, за исключением случаев, когда система временно разблокирует его внутри. Этот механизм можно использовать для замораживания прокинутых свойств (props) или деревьев состояния Vuex вне мутаций.
- Улучшенные возможности отладки: мы можем точно отслеживать, когда и почему происходит перерисовка компонента или запускаются новые обработчики
renderTracked
иrenderTriggered
:
Другие улучшения
TL;DR: меньшие, более быстрые, tree-shaking friendly, фрагменты и порталы, Render API.
- Меньше: новая кодовая база спроектирована с нуля как tree-shaking friendly. Такие функции, как встроенные компоненты (
<transition>
,<keep-alive>
) и директивы-помощники (v-model
), теперь импортируются по требованию. Размер новой runtime библиотеки <10kb в gzip. Также мы можем предлагать больше встроенных функций в будущем, не прибегая к утяжелению полезной нагрузки для пользователей, которые их не используют. - Быстрее: на предварительных тестах мы видим повышение производительности на 100% по всем направлениям, включая необработанное обновление и исправление Virtual DOM (мы узнали немало трюков от Inferno, самой быстрой реализации Virtual DOM), инициализацию экземпляра компонента и отслеживаемых данных. 3.0 будет снижать половину времени, затраченного на JavaScript, когда ваше приложение загрузится.
- Фрагменты и порталы: несмотря на уменьшение размера, 3.0 поставляется со встроенной поддержкой фрагментов (компонент, возвращающий несколько корневых узлов) и порталов (рендеринг поддерева в другой части DOM, а не внутри компонента).
- Улучшенный механизм слотов: все слоты, созданные с помощью компилятора, теперь являются функциями и вызываются во время вызова рендеринга дочернего компонента. Это гарантирует, что зависимости в слотах собираются в качестве зависимостей для дочернего элемента вместо родителя. Это означает, что:
- При изменении содержимого слота только дочерний компонент перерисовывается
- Когда родительский компонент перерисовывается, то дочерний не должен, если его содержимое слота не изменилось. Это изменение предлагает еще более точное обнаружение изменений на уровне дерева компонентов, поэтому меньше ненужных повторных рендерингов!
- Render API: Новый API ES-классов упростит рендер для проектов, таких как Weex и NativeScript Vue. Это также упростит создание пользовательских рендер функций для различных целей.
Улучшения компилятора *
TL;DR: tree-shaking friendly вывод, оптимизация AOT, парсер с лучшей информацией об ошибках и поддержкой source maps.
- При использовании ссылок на связующие компоненты, зависящие от дерева, шаблоны, которые используют дополнительные функции, будут генерировать код, который импортирует эти функции с использованием синтаксиса модулей ES. Таким образом, неиспользуемые необязательные функции удаляются из бандла.
- Из-за улучшений в новой реализации Virtual DOM мы также можем выполнять более эффективные оптимизации при компиляции, такие как статический подъем дерева, статический подъем свойств, подсказки компилятора, чтобы пропустить нормализацию дочерних элементов, более быстрые способы создания VNode и т. д.
- Мы планируем переписать синтаксический анализатор для улучшения информации об ошибках компиляции шаблона. Это также должно привести к поддержке source maps, а новый парсер может служить основой для интеграции сторонних инструментов, таких как
eslint-plugin-vue
и IDE.
Поддержка IE11 *
TL;DR: он будет поддерживаться, но в отдельной сборке с теми же ограничениями на реактивность Vue 2.x.
Новая кодовая база в настоящее время предназначена только для вечнозеленых браузеров и предполагает базовую поддержку ES2015. Но, увы, мы знаем, что многим нашим пользователям по-прежнему необходимо поддерживать IE11 в обозримом будущем. Большинство используемых функций ES2015 могут быть переписаны/заполифиллены для IE11, за исключением Proxies. Наш план заключается в альтернативной реализации наблюдателя с тем же API, но с использованием старого Object.defineProperty
API. Отдельная сборка Vue 3.x будет доступна с использованием этой реализации. Тем не менее, эта сборка будет подвергаться тем же изменениям, что и Vue 2.x, и, таким образом, не полностью совместима с "современной" сборкой 3.x. Мы осознаем, что это накладывает некоторые неудобства для авторов библиотек, поскольку им нужно знать о совместимости для двух разных билдов, но мы обязательно предоставим четкие рекомендации по этому вопросу, когда достигнем этого этапа.
Как мы намерены это делать
Прежде всего, хоть мы и объявляем об этом сегодня, у нас пока нет окончательного плана действий. На данный момент мы знаем, какие шаги мы предпримем:
1. Внутренняя обратная связь
Это та фаза, в которой мы сейчас находимся. В настоящее время у нас уже есть прототип, который включает в себя новую реализацию наблюдателя, Virtual DOM и компонентную реализацию. Мы пригласили группу авторов влиятельных проектов сообщества для обеспечения обратной связи для внутренних изменений и хотели бы, чтобы они были довольны изменениями, прежде чем двигаться вперед. Мы хотим обеспечить, чтобы важные библиотеки в экосистеме были готовы в то же самое время, когда мы выпустим 3.0, чтобы пользователи, которые полагались на эти проекты, могли легко обновляться.
2. Публичная обратная связь через RFC
Как только мы обретем определенный уровень уверенности в новом дизайне, на каждое изменение мы откроем специальную проблему RFC, которая включает в себя:
- Масштаб изменения
- Основываясь на изменениях: что мы получаем и какие компромиссы выполняются
- Путь обновления: может ли он быть представлен полностью обратно совместимым способом и с помощью чего?
Мы будем ожидать отзывов от более широкого сообщества, чтобы они помогли нам воплотить эти идеи.
3. Ввод совместимых функций в 2.x и 2.x-next
Мы не забываем о 2.x! Фактически, мы планируем использовать 2.x для постепенного приучения пользователей к новым изменениям. Мы постепенно вводим подтвержденные изменения API в 2.x через адаптеры opt-in
, а 2.x-next позволит пользователям опробовать новую реализацию наблюдателя на основе Proxy.
Последняя минорная версия в 2.x станет LTS и продолжит получать исправления ошибок и исправлений в течение 18 месяцев, когда будет выпущена Vue 3.0.
4. Альфа фаза
Мы закончим компилятор и серверную часть 3.0 и начнем создавать альфа-релизы. В основном это будет для тестирования стабильности в небольших приложениях.
5. Бета фаза
В бета-фазе нашей главной задачей является обновление библиотек поддержки и таких инструментов, как Vue Router, Vuex, Vue CLI, Vue DevTools и убедиться, что они работают исправно с новым ядром. Мы также будем работать с крупными библиотечными авторами из сообщества, чтобы помочь им подготовиться к версии 3.0.
6. RC фаза
После того как мы добьемся стабильности API и кодовой базы, мы войдем в RC-фазу с замораживанием API. На этом этапе мы также будем работать над сборкой "compat build": сборка 3.0, включающая уровни совместимости для API 2.x. Эта сборка также будет поставляться с флагом, который вы можете включить, чтобы выпустить предупреждения об устаревании для использования API 2.x в вашем приложении. Сопоставление сборки можно использовать в качестве руководства для обновления вашего приложения до версии 3.0.
7. IE11 сборка
Последней задачей перед окончательной версией будет сборка, совместимая с IE11, как было указано выше.
8. Окончательный релиз
Честно говоря, мы не знаем, когда это произойдет еще, но, вероятно, в 2019 году. Опять же, мы больше заботимся о доставке того, что является надежным и стабильным, а не обещающим конкретные даты. Есть много работы, которую нужно сделать, но мы взволнованы тем, что будет дальше!