На прошлой неделе на 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, а не внутри компонента).
  • Улучшенный механизм слотов: все слоты, созданные с помощью компилятора, теперь являются функциями и вызываются во время вызова рендеринга дочернего компонента. Это гарантирует, что зависимости в слотах собираются в качестве зависимостей для дочернего элемента вместо родителя. Это означает, что:
    1. При изменении содержимого слота только дочерний компонент перерисовывается
    2. Когда родительский компонент перерисовывается, то дочерний не должен, если его содержимое слота не изменилось. Это изменение предлагает еще более точное обнаружение изменений на уровне дерева компонентов, поэтому меньше ненужных повторных рендерингов!
  • 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 году. Опять же, мы больше заботимся о доставке того, что является надежным и стабильным, а не обещающим конкретные даты. Есть много работы, которую нужно сделать, но мы взволнованы тем, что будет дальше!

Комментарии (9)


  1. vintage
    04.10.2018 08:52

    Я обычно презентую $mol, выпущенный пару лет назад, как фреймворк будущего. Давайте посмотрим, куда движется Vue..


    3.0 будет поддерживать компоненты на основе классов изначально

    Что было изначально в $mol. Любой компонент — не более чем класс, реализующий определённый АПИ.


    Кодовая база 3.x сама будет написана на TypeScript и обеспечит улучшенную поддержку TypeScript.

    Что было изначально в $mol. Даже шаблоны проверяются TS компилятором.


    чтобы избежать глобального вмешательства в прототип Vue при установке плагинов. Вместо этого плагины будут применены и привязаны к дереву компонентов.

    Что было изначально в $mol. К любому компоненту можно приаттачить набор плагинов и использовать их для расширения функциональности.


    Ленивое наблюдение по-умолчанию.

    Что было изначально в $mol. Более того, ленивое не только наблюдение, но и все вычисления, позволяя, например, не загружать данные, которые не нужны для рендеринга в текущий момент.


    Меньше: новая кодовая база спроектирована с нуля как tree-shaking friendly.

    Что было изначально в $mol. Более того, вместо того, чтобы подключать пакет, а потом вырезать лишнее с помощью tree-shaking, в $mol лишний код не подключается изначально. А всё потому, зависимостями управляет автоматика, а не вручную.


    рендеринг поддерева в другой части DOM, а не внутри компонента

    Что было изначально в $mol. Без всяких порталов можно любой компонент отрендерить в любом другом или вообще в стороне от приложения. Вся фишка в том, что компоненты в $mol — самодостаточные, не зависящие от окружения. Любой компонент может быть приложением, а любое приложение — компонентом.


    все слоты, созданные с помощью компилятора, теперь являются функциями и вызываются во время вызова рендеринга дочернего компонента.

    Что было изначально в $mol. Более того, тот же принцип действует в любых направлениях. Например, часть родителя может быть функцией от свойств детей, что активно применяется для ленивого рендеринга.


    Размер новой runtime библиотеки <10kb в gzip.

    Что было изначально в $mol. Точнее не так, как такового рантайма в $mol нет, просто в бандл попадают те модули, которыми воспользовались. Но реактивный "привет мир" как раз 10кб и занимает.


    Так что использовать $mol становится всё меньше и меньше поводов, что является весьма позитивной тенденцией.


    1. flymithra
      04.10.2018 12:46
      +5

      > Твой $mol
      image


    1. vdasus
      04.10.2018 15:03
      +3

      Вы уверены, что так назойливо рекламируя свой мол достигнете своей цели? Я уже давно *заставляю* себя читать ваши посты в которых упоминается мол. Как правило не читая можно предсказать все что вы напишете: «Вы тут все не цените — ах какая у меня конфетка».

      Мне кажется вам надо менять или метод продвижения или стиль общения. Не знаю что вам поможет. Но, чисто подсознательно, я уже не выберу мол как бы он ни был хорош. Только если что-то меня заставит.


      1. vintage
        04.10.2018 22:22

        Не используйте, пожалуйста, $mol. Не лишайте меня конкурентного преимущества.


      1. riot26
        05.10.2018 02:55
        +1

        Невольно вспоминаются посты о PHPixie и PocketBook


    1. unel
      05.10.2018 17:25

      Что было изначально в $mol. Более того, тот же принцип действует в любых направлениях. Например, часть родителя может быть функцией от свойств детей, что активно применяется для ленивого рендеринга.


      Ухты! Выглядит, как необычный способ выстрелить себе в ногу, но, не смотря на это, интересно, как это реализовано. Выходит так, что
      — свойства детей могут быть изменены не только родительским компонентом (если нет, то почему бы родителю просто не опираться на эти свойства, которые он и прокидывает детям)?
      — родительский компонент как-то подписывается на свойства детей?
      Или как-то иначе?

      И ещё вопрос: детектится ли как-то при этом зацикливание? Например, когда родитель, реагируя на изменение свойства ребёнка, меняет его другое свойство, а ребёнок отрабатывает это изменение и меняет первое свойство, на которое опять реагирует родитель, и так до бесконечности.


      1. vintage
        05.10.2018 17:45

        Да, данные могут приходить разными окольными путями. Но я говорил про кейс, когда родителю нужны компоненты их детей. Например, возьмём диаграммы. В компонент диаграммы передаётся список графиков. Диаграмма узнаёт у них диапазоны по горизонтали и вертикали, вычисляет общий диапазон и позиционирует графики так, чтобы все влезли. Потом у каждого графика запрашивает превьюшку и название и рендерит легенду внизу с соответствующими превьюшками и названиями. И разумеется, если график решит изменить свой цвет, название или ещё что, то легенда отразит это изменение.


        Компоненты — просто классы со свойствами, а свойства уже автоматически трекают зависимости друг между другом благодаря ОРП. В VueJS тоже свойства через орп синхронизируются, но оно гвоздями прибито к компонентам.


        Состояния организуются как функции от других состояний. Реактивные циклические зависимости, конечно же, детектятся и приводят к исключениям.


  1. babylon
    05.10.2018 02:14
    -1

    Дмитрий, вас то кто заставил заниматься $mol? Я ни разу не использовал $mol но думаю что он хорош. Точно лучше Angular и React, но уже не лучше Vue Я также думаю, что если бы в основе лежал jsonnet он был бы всё ещё лучше, но это был бы уже не $mol, потому что идеи заложенные в архитектуре $mol на мой взгляд исчерпаны


    1. vintage
      05.10.2018 06:50
      -1

      Дмитрий, вас то кто заставил заниматься $mol?

      Просто я мазохист. Люблю боль и страдания. А $mol доставляет мне их максимальное количество на единицу кода.


      Я ни разу не использовал $mol но думаю что он хорош.

      Ну зачем вы обманываете себя? Попробуйте использовать и сразу поймёте, что у него непонятные шаблоны, все компоненты кривые, все демки тормозят, а документации так вообще нет.


      Точно лучше Angular и React, но уже не лучше Vue

      Если бы $mol был лучше, чем Angular или даже, прости господи, React, то звёздочек у него было бы куда больше, чем у них. Однако у $mol звёздочек в 1000 раз меньше! Выводы, думаю, очевидны.


      Я также думаю, что если бы в основе лежал jsonnet он был бы всё ещё лучше

      Это же просто генератор json-а. При чём тут фреймворки? Этим jsonnet-ом можно для любого фреймворка данные подготовить.


      идеи заложенные в архитектуре $mol на мой взгляд исчерпаны

      Да какая там архитектура? Просто навалили в корень репозитория кучу модулей без какой-либо группировки лишь бы их имена в глобальном (!) скоупе были короткими. Это ж надо было додуматься в 2k18 использовать неймспейсы вместо нативных модулей.