JavaScript

Новинки влияющие на производительность во Vue.js версии 3

Spread the love

В последнее время мы все больше и больше слышим о предстоящем выпуске третьей версии Vue.js. Несмотря на то, что еще не все определено, мы можем с уверенностью предположить, что будут значительные улучшение по сравнению с текущей версией (которая и так выдающаяся). Команда Vue проделывает потрясающую работу по улучшению API фреймворков. Evan You описал цели для Vue 3 следующим образом:

  • Сделать его быстрее
  • Сделать его меньше
  • Упростить его поддержку
  • Сделать вашу жизнь проще

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

Оптимизация производительности

Прежде чем углубиться в некоторые API, я хотел бы поговорить о производительности Vue 3. И есть о чем поговорить! Мы можем найти значительные улучшения практически по любым критериям!

Давайте начнем с размера сборки Vue 3.

В настоящее время минифицированный и сжатый пакет Vue занимает около 20 КБ (22,8 КБ для текущей версии 2.6.10). Пакет Vue 3, по оценкам, весит около половины этого, всего ~ 10kB!

Глобальное tree-shaking API

Есть другие оптимизации, такие как лучшая модульность, исходный код Vue 3 будет tree-shakeable. Это означает, что если вы не используете некоторые из его функций (например, компонент <keep-alive> или директиву v-show), они не будут включены в вашу сборку. В настоящее время, независимо от того, какие функции мы используем из ядра Vue, все они попадают в наш производственный код, поскольку экземпляр Vue экспортируется как один объект, и упаковщики не могут определить, какие свойства этого объекта были использованы в коде.

 // Vue 2.x - whole `Vue` object is bundled for production 
import Vue from 'vue'

Vue.nextTick(() => {})
const obj =  Vue.observable({})

Чтобы сделать глобальное API-совместимым с tree-shakeable интерфейсом API, команда Vue решила импортировать большинство из них через именованные экспорты, чтобы упаковщики могли обнаруживать и удалять неиспользуемый код:

 // Vue 3.x - only imported properties are bundled
import { nextTick, observable } from 'vue'

nextTick(() => {})
const obj = observable({})

Это изменение влияет на:

  • Vue.nextTick
  • Vue.observable
  • Vue.version
  • Vue.compile (только в полной сборке)
  • Vue.set (только в сборках совместимости 2.x вы скоро узнаете, почему)
  • Vue.delete (так же, как и выше)

Это займет некоторое время, пока эта идея будет принята в экосистеме. Поэтому команда Vue выпустит сборки совместимости, и у нас будет возможность использовать плагины, которые также используют старое API. Так же под капотом компилятор Vue (инструмент, который преобразует шаблон Vue в функцию рендеринга) будет обнаруживать директивы, используемые в шаблонах, и обрабатывать их как tree-shakeable. Например шаблон ниже:

<transition>
  <div v-show="ok">hello</div>
</transition>

после обработки компилятором Vue будет выглядеть примерно так:

import { h, Transition, applyDirectives, vShow } from 'vue'

export function render() {
  return h(Transition, [
    applyDirectives(h('div', 'hello'), this, [vShow, this.ok])
  ])
}

Каждый получит выгоду от глобального tree-shakable API (особенно наши пользователи), но я думаю, что люди, которые делают небольшие и легкие веб-сайты и используют только часть функций Vue для интерактивности в качестве замены для библиотек, таких как jQuery, оценят это больше всего.

Реактивность основаная на Proxy

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

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

Давайте начнем с одной из самых эффективных — новой системы реактивности, основанной на JavaScript Proxies. Текущая система реактивности Vue основана на Object.defineProperty, которая имеет некоторые ограничения. Наиболее распространенным и разочаровывающим является тот факт, что Vue не может отслеживать добавление/удаление свойств реактивных объектов. Нам нужно было использовать Vue.set и Vue.delete для этих целей, чтобы система реактивности работала как задумано. С JS Proxies мы можем наконец избавиться от этого уродливого обходного пути.

// Добавление нового свойства к реактивному объекту в Vue 2.x
Vue.set(this.myObject, key, value) 
// Добавление нового свойства к реактивному объекту в Vue 3
this.myObject[key] = value

Реальное влияние прокси-серверов можно увидеть в гораздо более быстрой инициализации компонентов. Согласно тестам это примерно в 2 раза быстрее!

Причина такого улучшения особенно важна в связи с тем, что с помощью методов getter/setter Vue пришлось рекурсивно просматривать все объекты и их свойства и преобразовывать их. С прокси этот процесс намного проще.

Важно отметить, что при использовании JS Proxies Vue 3 откажется от поддержки Internet Explorer (это не касается Edge), но не беспокойтесь — будет сборка совместимости для тех, кто хочет поддерживать IE.

Time slicing

Обновление: Согласно твиту от Evan You, эта функция не будет включена в Vue 3.

Другая действительно захватывающая, но редко упоминаемая особенность производительности Vue 3 — экспериментальная поддержка Time Slicing.

Я использую пример, чтобы объяснить, что такое Time Slicing. Представьте очередь за мороженым. Очень длинную, потому что это лучшее мороженое в городе. После того, как один человек обслужен, будет другой, потом другой и т. д. И по какой-то причине нет информации о доступных вкусах мороженного. Чтобы получить эту информацию, вам нужно спросить об этом женщину, которая продает мороженое.

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

Это не лучшая ситуация для клиентов хотящих узнать доступные вкусы мороженого, и большинство из них, вероятно, не захотят стоять в очереди. Чтобы решить эту проблему, женщина может ответить на один вопрос после каждых 2-3 обслуживаемых клиентов из первой очереди. Тогда обе очереди будут довольны этой ситуацией.

Именно так процессор работает с веб-приложениями. У нас есть «главная» очередь (которая называется «основной поток»), которая должна выполнить все свои основные задачи (сценарии, рендеринг и т. д.), Прежде чем она сможет реагировать на взаимодействия с пользователем. На некоторых страницах это может привести к очень плохому пользовательскому взаимодействию в зависимости от того, сколько потребуется для загрузки или повторного рендеринга компонентов Vue.

Чтобы сделать его более надежным, гораздо лучше «разрезать» этот сценарий на части и посмотреть, есть ли пользовательский ввод, который нужно обработать после каждого фрагмента. Таким образом, приложение останется отзывчивым независимо от того, сколько рендеринга или повторного рендеринга должно произойти. Именно так это и будет работать в Vue 3.

Вот как Evan You представил функцию Time Slicing в Vue 3. Обратите внимание на небольшие промежутки во временной шкале выполнения скрипта, они предназначены для обработки пользовательского ввода.

Возможность легко определить, почему компонент перерисован

Инструменты очень важны для оценки производительности. В соответствии с этим в Vue 3 будет новый хук жизненного цикла — renderTriggered. Его можно использовать для отслеживания и устранения ненужных повторных визуализаций компонентов, что является очень мощным оружием в оптимизации производительности во время выполнения, особенно когда он будет объединен с Time Slicing.

const Component = {
  // other properties
  renderTriggered (event) {
     console.log(`Re-render of ` + this.$options.name + ` component`, event)
  }
}

Что еще

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

Но есть несколько улучшений, о которых стоит упомянуть:

  • Получаемый код станет легче оптимизировать для компилятора JavaScript
  • Так же получаемый код будет в целом гораздо лучше оптимизирован
  • Из-за улучшенных алгоритмов будет предотвращен ненужный повторный рендеринг parent/children

Кроме того, в предстоящие дни вы можете ожидать от Evan You более подробные статьи об оптимизации производительности, с описанием компилятора Vue (я обновлю статью ссылкой после ее публикации).

Заключение

Несмотря на то, что Vue уже признан одним из самых эффективных фреймворков, мы увидим значительные улучшения в 3-м выпуске. Особенно в размере сборки и производительности во время выполнения. Также будет сделано множество микрооптимизаций. Я думаю, что Vue 3 идеально впишется в современный мобильный и ориентированный на производительность веб.

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

Оригинальная статья: Filip Rakowski — Faster Web Applications with Vue 3

Была ли вам полезна эта статья?
[6 / 5]

Spread the love
Editorial Team

Recent Posts

Vue 3.4 Новая механика v-model компонента

Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование​ v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…

11 месяцев ago

Анонс Vue 3.4

Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…

11 месяцев ago

Как принудительно пере-отобразить (re-render) компонент Vue

Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…

2 года ago

Проблемы с установкой сертификата на nginix

Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…

2 года ago

Введение в JavaScript Temporal API

Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…

2 года ago

Когда и как выбирать между медиа запросами и контейнерными запросами

Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…

2 года ago