![Screenshot-1](https://habrastorage.org/getpro/habr/post_images/06f/124/556/06f124556abe1bec9eb55bccae58e759.png)
Одним из самых ярких событий в мире Фронтенда в этому году стала публикация репозитория Vue next — части функционала третьей версии VueJS. В этой статье представлен обзор новых killer features VueJS. На момент публикации статьи репозиторий находился в статусе Pre-Alpha. Планы на релиз можно посмотреть в Roadmap
Предыстория
В феврале 2018 Evan You, создатель Vue.js, поделился планами на 3 версию популярного фреймворка:
- Разбить функциональность на пакеты для изоляции области видимости
- В кодовой базе появится TypeScript
- Vue 3 будет иметь обратную совместимость со 2й версией (т.е. не сломает старый код)
- Наблюдатели в 3.0 версии основаны на Proxy, что увеличит скорость рендера и снимет ряд ограничений накладываемых
Object.defineProperty
- Появится возможность дебажить с помощью новых хуков
renderTracked
иrenderTriggered
- Благодаря введению tree shaking (исключение из билда неиспользуемых директив) размер фреймворка составит меньше 10kb в сжатом виде
- Оптимизация слотов
- Перфоманс во vue 3 улучшится на 100%
Features such as built-in components and directive runtime helpers (v-model) are now imported on-demand and tree-shakableКомпилятор будет отслеживать наличие директив и включать их в билд на стадии компиляции.
Evan You
В процессе работы над Vue 3 Эван отказался от переписывания компонентов на классы и вместо этого внедрил функциональное API.
Поскольку новая версия будет использовать Proxy, которые не поддерживаются в IE, Эван планирует сделать отдельный билд для IE11. Всего обещают 4 фазы:
- Alpha Phase — стадия доработки компилятора и ssr-рендера
- Beta Phase — стадия доработки основных библиотек (Vue Router, Vuex, Vue CLI, Vue DevTools)
- RC Phase — стадия пререлиза, включающая в себя Vue 2.0
- IE11 build
- Final Release
Финальный релиз Эван запланировал на 2019 год, но проект все еще в стадии пре-альфа.
Vue 3 будет быстрее
Благодаря ряду нововведений Vue 3 станет в 2 раза быстрее предыдущей версии.
Proxy-based Observation and Reactivity
Одним из крупных нововведений стало изменение механизма наблюдения за объектами с геттеров и сеттеров Object.defineProperty на Proxy. Теперь Vue может отслеживать удаление и добавление свойств реактивных объектов без использования Vue.set и Vue.delete. Нововведение увеличило скорость рендеринга и скриптинга и уменьшило потребление памяти в 2 раза! Сравнить перфоманс Vue 2 и Vue 3 можно, скачав репозиторий Ильи Климова
Сравнение производительности Vue 2 (слева) и Vue 3 (стадия pre-alpha, справа)
![Screenshot-1](https://habrastorage.org/getpro/habr/post_images/951/84a/318/95184a318fbf8d76a644ef2f23fdb206.png)
Благодаря проксям не потеряется реактивность при изменении не отслеживаемых во Vue 2 манипуляций с объектами. Теперь Vue не будет рекурсивно проходить по свойствам объекта, чтобы вычислить изменения.
Что выполнено из обещаний:
- Компоненты-потомки и родители перерисовываются независимо
- Уменьшился размер Vue 3 с 20kb до 10kb в сжатом виде
- Добавлен TypeScript
Другие оптимизации:
- Vue 3 будет запоминать статичный контент и патчить только динамические данные
- Статичные пропсы поднимутся наверх области видимости
- Для простоты разработки код Vue 3 разбит на модульные пакеты
- Пакет runtime-core сделан кроссплатформенным
- Вместо классов Эван добавил setup функцию и хуки, благодаря которым код становится чистым, организованным и переиспользуемым*
- Time Slicing*. Выполнение JS кода нарезается на куски, не блокируя взаимодействие пользователя с приложением
Звездочками отмечено экспериментальное API.
Update: Позже Эван решил отказаться от time sliсing
Вдохновившись HOC Реакта Эван реализовал setup функции с переиспользуемой логикой и кастомными хуками. В отличие от миксинов хуки жизненного цикла не перезаписывают друг друга.
Усовершенствованный патч VDom
Хойстинг статического контента
![Screenshot-2](https://habrastorage.org/getpro/habr/post_images/9cb/415/c75/9cb415c752e339ffec2664b23cf31ad2.png)
Статичный контент выносится за пределы патчинга VDom при компиляции шаблона. На это команду Vue вдохновил Svelte:
<div>Hello, {{name}}</div>
Здесь передается объект changed и контекст. Если changed содержит реактивную переменную, то она обновляется в контексте.
p(changed, ctx) {
if(changed.name) {
set_data(t1, ctx.name);
}
}
В предыдущей реализации компилятор Vue проходился по всем нодам, включая статичные:
function render(){
const children = [];
for(let i = 0; i < 5; i++) {
children.push(h('p', {
class: 'text'
}, i === 2 ? this.message : 'Lorem upsum'))
}
return h('div', { id: 'content' }, children)
}
Новая стратегия компиляции шаблонов
В новой версии шаблон разбивается на блоки:
![Selection-002](https://habrastorage.org/getpro/habr/post_images/c0f/a65/25e/c0fa6525eca7377713ef1f6fae4bdb79.png)
- Шаблон делится на блоки
- Структура нод внутри каждого блока полностью статична
- Для отслеживания динамических значений в блоке требуется только 1 плоский массив, куда они помещаются
С новой стратегией производительность напрямую зависит от количества динамического контента вместо размера шаблона.
Vue 3 будет лучше адаптирован под большие проекты
Большие проекты сталкиваются со следующими проблемами при использовании Vue:
- Не идеальная поддержка TypeScript
- Массивные, сложно поддерживаемые компоненты
- Отсутствие простого паттерна для переиспользования кода
Изначально для поддержки TS планировалось добавить классы. Но команда Vue столкнулась с проблемами:
- Подмешивать пропсы и другие атрибуты к this проблематично
- Декораторы для ES6 классов в TC39 нестабильны
Команда Эвана запросила помощь у экспертов из TC39 и выяснила, что подобная реализация могла бы конфликтовать с плагинами, которые примешивают различные пропсы и атрибуты к контексту Vue.
Потенциально эти проблемы могли решить декораторы, но они находятся в разработке.
Composition API
Команда Vue вдохновилась хуками Реакта и решила создать подобное API. Оно опционально и находится в стадии разработки и обсуждения, поэтому некоторые названия могут меняться.
Главная концепция этого изменения — организовать код компонента логичнее, разбив его на смысловые блоки. Подробнее про composition API можно прочитать в документации.
Пример использования Vue 3. Компонент разбивается на логические функции, внутри которых можно использовать реактивность и хуки жизненного цикла.
Импортируем новые хуки из composition API:
import { reactive, computed, onMounted } from '@vue/composition-api';
export default {
setup() {
const { state } = countAnimal("rabbit")
const { getType, anotherState } = anotherCount()
return {
state,
getType,
anotherState
}
}
}
В функции countAnimal есть реактивные свойства count, animal и метод increment. При нечетном счетчике имя животного меняется. Счетчик запускается при монтировании компонента.
function countAnimal(name) {
const state = reactive({
count: 0,
animal: computed(() => state.count % 2 ? name : 'bear')
})
function increment() {
setTimeout(() => {
state.count++;
increment()
}, 1000)
}
onMounted(() => {
increment()
})
return {
state
}
}
Создаем другую функцию anotherCount, которая тоже содержит метод increment и state с счетчиком и названием животного. В метод getType передается название животного из шаблона.
function anotherCount() {
const anotherState = reactive({
count: 0,
animal: 'fox'
})
function getType(name) {
return name == 'bear' ? 'slow' : 'fast'
}
function increment() {
setTimeout(() => {
anotherState.count+=10;
increment()
}, 1000)
}
onMounted(() => {
increment()
})
return {
getType,
anotherState
}
}
В шаблоне выводятся 2 счетчика и 2 имени животных. Тип бега меняется в зависимости от имени животного.
<template>
<div>
<div>Count {{state.animal}}: {{ state.count }}</div>
<div>{{state.animal}} runs {{getType(state.animal)}}</div>
<div>Another:
Count {{anotherState.animal}}: {{ anotherState.count }}</div>
</div>
</template>
Новые хуки используются внутри setup, не ломая старый API. Обратите внимание, что onMounted ссылается на единый хук жизненного цикла компонента.
У такого апи есть ряд преимуществ:
- Хуки жизненного цикла не перетирают друг друга
- Понятен источник свойств
- Не создаются дополнительные экземпляры компонента
Заключение
Выше перечислены самые важные изменения во Vue 3. Большинство улучшений будут скрыты под капотом сгенерированного компилятором кода.
Основные улучшения:
- Сгенерированный код оптимальнее для JS компилятора
- Сгенерированный bundle легче
- Компоненты родителей/потомков перерисовываются благодаря улучшенному алгоритму патчинга
Vue успел зарекомендовать себя, как один из самых быстрых и оптимальных фреймворков. Новая версия станет еще быстрее и легче. Vue 3 отлично подходит для современного мобильно- и перфоманс-ориентированного веба. Комментарий о будущих изменениях можно оставить в официальном RFC (request for comments).
P.S. Спасибо за исправление опечаток.
CyberTopTuK
Time slicing was removed from 3.0
https://github.com/vuejs/rfcs/issues/89#issuecomment-546988615