- PVSM.RU - https://www.pvsm.ru -

Vue 3 станет быстрее

Screenshot-1 [1]
Одним из самых ярких событий в мире Фронтенда в этому году стала публикация репозитория Vue next [2] — части функционала третьей версии VueJS. В этой в этой статье представлен обзор новых killer features VueJS. На момент публикации статьи репозиторий находился в статусе Pre-Alpha. Планы на релиз можно посмотреть в Roadmap [3]

Предыстория

В феврале 2018 Evan You, создатель Vue.js, поделился планами [4] на 3 версию популярного фреймворка:

  • Разбить функциональность на пакеты для изоляции области видимости
  • В кодовой базе появится TypeScript
  • Vue 3 будет иметь обратную совместимость со 2й версией (т.е. не сломает старый код)
  • Наблюдатели в 3.0 версии основаны на Proxy, что увеличит скорость рендера и снимет ряд ограничений накладываемых Object.defineProperty
  • Появится возможность дебажить с помощью новых хуков renderTracked и renderTriggered
  • Благодаря введению tree shaking (исключение из билда неиспользуемых директив) размер фреймворка составит меньше 10kb в сжатом виде
  • Оптимизация слотов
  • В 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 фазы:

  1. Alpha Phase — стадия доработки компилятора и ssr-рендера
  2. Beta Phase — стадия доработки основных библиотек (Vue Router, Vuex, Vue CLI, Vue DevTools)
  3. RC Phase — стадия пререлиза, включающая в себя Vue 2.0
  4. IE11 build
  5. 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 можно, скачав репозиторий Ильи Климова [5]

Сравнение производительности Vue 2 (слева) и Vue 3 (стадия pre-alpha, справа)
Screenshot-1 [6]

Благодаря проксям не потеряется реактивность при изменении не отслеживаемых во Vue 2 манипуляций с объектами. Теперь Vue не будет рекурсивно проходить по свойствам объекта, чтобы вычислить изменения.
Что выполнено из обещаний:

  • Компоненты-потомки и родители перерисовываются независимо
  • Уменьшился размера Vue 3 с 20kb до 10kb в сжатом виде
  • Добавлен TypeScript

Другие оптимизации:

  • Vue 3 будет запоминать статичный контент и патчить только динамические данные
  • Статичные пропсы поднимутся наверх области видимости
  • Для простоты разработки код Vue 3 разбит на модульные пакеты
  • Пакет runtime-core сделан кроссплатформенным
  • Вместо классов Эван добавил setup функцию и хуки, благодаря которым код становится чистым, организованным и переиспользуемым*
  • Time Slicing*. Выполнение JS кода нарезается на куски, не блокируя взаимодействие пользователя с приложением

Звездочками отмечено экспериментальное API.
Вдохновившись HOC Реакта Эван реализовал setup функции с переиспользуемой логикой и кастомными хуками. В отличие от миксинов хуки жизненного цикла не перезаписывают друг друга.

Усовершенствованный патч VDom

Хойстинг статического контента
Screenshot-2 [7]
Статичный контент выносится за пределы патчинге 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 [8]

  • Шаблон делится на блоки
  • Структура нод внутри каждого блока полностью статична
  • Для отслеживания динамических значений в блоке требуется только 1 плоский массив, куда они помещаются

С новой стратегией производительность напрямую зависит от количества динамическего контента вместо размера шаблона.

Vue 3 будет лучше адаптирован под большие проекты

Большие проекты сталкиваются со следующими проблемами при использовании Vue:

  1. Не идеальная поддержка TypeScript
  2. Массивные, сложно поддерживаемые компоненты
  3. Отсутсвие простого паттерна для переиспользования кода

Изначально для поддержки TS планировалось добавить классы. Но команда Vue столкнулась с проблемами:

Команде Эвана запросила помощь у экспертов из TC39 и выяснила, что подобная реализация могла бы конфликтовать с плагинами, которые примешивают различные пропсы и атрибуты к контексту Vue.
Потенциально эти проблемы могли решить декораторы, но они находятся в разработке.

Composition API

Команда Vue вдохновилась хуками Реакта и решила создать подобное API. Оно опционально и находится в стадии разработки и обсуждения, поэтому некоторые названия могут меняться.
Главная концепция этого изменения — организовать код компонента логичнее, разбив его на смысловые блоки. Подробнее про composition API можно прочитать в документации [10]
Пример использования 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 [11](request for comments)

Автор: sashavoloh

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/338756

Ссылки в тексте:

[1] Image: https://ibb.co/nBDvXqV

[2] Vue next: https://github.com/vuejs/vue-next

[3] Roadmap: https://github.com/vuejs/vue/projects/6

[4] поделился планами: https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf

[5] скачав репозиторий Ильи Климова: https://gitlab.com/javascript-ninja/demos/vue3-performance-test

[6] Image: https://ibb.co/HBgft8C

[7] Image: https://ibb.co/b5GXQsq

[8] Image: https://imgbb.com/

[9] Декораторы для ES6 классов в TC39: https://github.com/tc39/proposal-decorators

[10] документации: https://vue-composition-api-rfc.netlify.com/#api-introduction

[11] RFC : https://github.com/vuejs/rfcs

[12] Источник: https://habr.com/ru/post/477228/?utm_campaign=477228&utm_source=habrahabr&utm_medium=rss