напишите в начале
Привет всем, яChanning.
Я только что закончил технический обмен информацией о Vue3 в отделе в прошлую пятницу. На подготовку контента ушло около недели времени и энергии, поэтому я хотел преобразовать его в текст и поделиться им с друзьями на выходных.
Может быть, некоторые части не совсем профессиональны, но определенно открыты для разумных мнений и предложений.
Основная часть данной статьи разделена на три части:Vue3重写的动机
,优化的原理
и что дает Vue3值得一看的新东西
.
Содержание специально разделено на следующую карту мозга:
Почему - Мотивация переписать?
Более профессионально можно увидеть собственный почерк Ю Да:The process: Making Vue 3
Мотивация переписывания в основном делится на два пункта:
- Используйте новые нативные функции JS
- Устранение дизайнерских и архитектурных недостатков
Используйте новые нативные функции JS
С развитием стандартизации внешнего интерфейса текущие основные браузеры обычно поддерживают множество новых функций JS, некоторые из которых не только решают многие проблемы с технической реализацией, но и улучшают производительность.
В Vue3 наиболее важным и известным является ES6.Proxy.
Прокси не только устраняет существующие ограничения в Vue2 (такие как добавление новых свойств объектов, прямая модификация элементов массива не будет запускать механизм реагирования, что также является так называемой ошибкой, как думают многие новички), но также имеет лучшая производительность:
Мы знаем, что перехват и перехват данных в Vue2 заключается в рекурсивном обходе объекта при инициализации компонента, установке его геттера и сеттера с помощью Object.defineProperty для каждого свойства, а затем вешании обработанных объектов в это над этим из экземпляр компонента, поэтому мониторинг данных таким образом находится на уровне свойств, поэтому добавленные свойства объекта не могут быть проверены.В то же время эта операция инициализации все еще является относительно дорогой операцией для ЦП. Для javascript чем стабильнее и меньше объект, тем выше производительность.
После использования Proxy инициализация компонентов не требует такой трудоемкой операции, т.к. Proxy - это реальное значение наматывания слоя прокси на объект для выполнения операции перехвата и угона данных, так что в целом сложность прям.На порядок меньше. Пока вы получаете доступ или изменяете содержимое объекта за прокси, оно может восприниматься этим уровнем прокси, а затем динамически решать, что вам возвращать, и вам больше не нужно повторять параметры для компонента. this экземпляра, поскольку у вас есть эта информация, когда вы обращаетесь к ней, вы знаете, принадлежит ли вещь, к которой вы обращаетесь, свойствам, данным или чему-то еще Vue нужно только извлечь ее из соответствующей структуры данных в соответствии с этой информацией, и все.Вы можете почувствовать, что объем памяти компонента уменьшился вдвое.
Поскольку прокси-сервер является прокси-сервером на уровне объекта, вы можете добавлять свойства к объекту, к которому можно проксировать.
Кроме того, Proxy также может проксировать массивы, поэтому даже если вы напрямую изменяете элементы в массиве, он может быть проксирован.
Однако для традиционного браузера - IE даже IE11 еще не поддерживает Proxy, а поскольку Proxy - это встроенная функция ES6, в настоящее время он несовместим с IE через полифилл (Vue3 также делает эту совместимость) ..... Эта штука действительно не имеет к нему никакого отношения, иначе при обновлении React до 15 Vue2.X не отказался бы от IE8. You Da также живо жаловался на IE на прошлогоднем VueConf — стоногий червь, мертвый, но не закоченевший.
IE сок хвоста мыши.
Устранение дизайнерских и архитектурных недостатков
С использованием и обслуживанием Vue2 постепенно выявляются некоторые конструктивные и архитектурные дефекты, в основном в том числе:
- Стыковка модулей внутри каркаса
- Плохая поддержка TypeScript.
- Неудачный опыт разработки крупномасштабных приложений
Итак, как эти проблемы решаются одна за другой в Vue3?
1. Разделите внутренние пакеты
Во-первых, у друзей, прочитавших исходный код Vue2, должно возникнуть глубокое чувство, очень больно разбираться в исходном коде фреймворка в одиночку.
Это проявляется в высокой степени связанности внутри каждого модуля и неявной связи плавающего кода, который, кажется, нигде не принадлежит, что также затрудняет поддержку и расширение исходного кода в сообществе.
Также из-за соединения внутренних модулей некоторым опытным продвинутым пользователям (например, авторам библиотек) приходится импортировать код всего фреймворка при построении средств визуализации более высокого уровня. Когда мы смотрим на исходный код Vue2, мы можем заметить, что в нем есть Weex. Это потому, что Weex — это многоцелевая среда рендеринга, официально сотрудничающая с Vue. Чтобы поддерживать эту возможность в Vue2, она ограничена существующим архитектуру и приходится разветвлять Codebase и копировать в нее много кода фреймворка, и что еще хуже, неофициальное сотрудничество вроде mpVue может только вручную вытащить весь код ветки Vue.
Чтобы решить эту проблему, Vue3 был переписан с использованиемmonorepo, разделить исходные модули, и весь фреймворк состоит из этих внутренних пакетов с низкой связанностью, каждый пакет имеет свой собственный API, определение типа, тестовую программу и т. д. С одной стороны, разработчикам становится легче читать, понимать и даже уверенно изменять эти пакеты модулей в больших масштабах.
С другой стороны, это также дает пользователю возможность вынимать некоторые из этих пакетов по отдельности, например, вы можете поставитьreactivityЭтот пакет, то есть отзывчивую систему, можно использовать в сценариях, где требуется отзывчивость, или вы можете использовать этот пакет для создания собственного игрушечного фреймворка и т. д.
2. Перепишите с помощью TypeScript и спроектируйте новый удобный для типов API
Говоря оTypeScript, Проблема, которая также должна нас беспокоить.
Во-первых, Vue2 изначально был написан на чистом JS, но позже понял, что система типов будет очень нужна для такого масштабного проекта, особенно при рефакторинге или расширении, проверка типов значительно уменьшит внесение аварий в этот процесс. Возможности для ошибок, но также позволяют большему количеству разработчиков кода вносить крупномасштабные изменения с большей уверенностью.
Итак, Vue2 представил FacebookFlowСтатическая проверка типов, с одной стороны, потому, что ее можно постепенно добавлять в существующие чистые JS-проекты, но, к сожалению, хотя Flow в какой-то степени и полезен, но не так благоухает, как ожидалось.Самое возмутительное, что кто бы думал, что даже Flow я тоже незаконченный.Вы можете пойти на официальный сайт Flow, чтобы увидеть.Эта вещь все еще находится в версии 0.X.По сравнению с быстрым развитием TypeScript и глубокой интеграцией TS и инструментов разработки, особенно VSCode, Поток действительно сложно описать Бар. Нельзя отрицать, что сам Ю Да сказал, что вначале он нажимал не то сокровище.
Кроме того, из-за бурного развития TS все больше и больше пользователей также используют TS в Vue.Для Vue одновременная поддержка двух систем типов является более хлопотной вещью, и это становится очень трудным в выводе типов. Если исходный код переключится на TS, это не будет таким уж дерьмом.
Во-вторых, причина, по которой поддержка TS в Vue2 является беспорядком, также заключается в том, чтоOptions APIсуществует между системой типоввинаиз.
Дизайн API Vue не был разработан для механизма и системы типов самого языка.Отчасти причина в том, что когда Vue был написан, в js не было даже системы типов.
Экземпляр компонента vue — это, по сути, объект, который содержит атрибуты, описывающие параметры компонента.Преимущество этого дизайна в том, что он больше соответствует человеческой интуиции, поэтому новичкам легче понять и использовать его.
Однако недостатком этого дизайна является то, что есть «ошибка» с системой типов, такой как TypeScript, Как сказать, эта ошибка не заметна для пользователей, которые сосредоточены только на бизнес-логике без системы типов.
API опций в Vue2 кажущийся объектно-ориентированным, но на самом деле имеет определенное отклонение, что делает его менее дружественным к типам, особенно для опций, вывод типа сложнее.
Но эта ошибка на самом деле двусторонняя: вы можете сказать, что дизайн optionsAPI недостаточно ориентирован на типы, или вы можете сказать, что TS недостаточно мощен, чтобы обеспечить достаточно хорошую поддержку типов для Vue.
Возьмите каштан, какJSXВ начале не было поддержки типов, потому что TypeScript принудительно добавил набор механизмов вывода типов для JSX, чтобы дать TSX текущий опыт разработки. Таким образом, можно понять, что если TypeScript не обеспечивал поддержку JSX, потому что в то время это не была настоящая спецификация JS, можно ли сказать, что существует разрыв между дизайном React и системой типов?
Итак, как сгладить эту ошибку во Vue? Прямой подход — перепроектировать удобный для типов API. Этот метод кажется простым, но для изменения API для Vue нужно учитывать множество вещей:
-
с оригинальным APIсовместимость: Можно ли одновременно поддерживать старый и новый API? Как старые пользователи могут обновиться? Конечно, напрямую изменить лицо, как Angular2 в то время, относительно просто, но прямой смысл в том, что независимо от жизни или смерти пользователей старой версии судьба известна всем. Теперь основные обновления версий основных фреймворков начали уделять достаточно внимания совместимости версий или прилагать к этому много усилий, например, официально выпущенный в октябре.React17, в этой версии нет новых API на уровне пользователя, но одна из интересных новых функций заключается в том, что приложение React может загружать несколько версий React одновременно, что позволяет постепенно обновлять более старые версии.
-
Как спроектировать дизайн, который может обеспечить хороший вывод типов, не влияя на процесс разработки пользователями, не являющимися TS? Как быть лучшим в TS и не TS опытеостаток средства такжепоследовательность? Это, безусловно, проще для пользователей, не являющихся TS, таких как Angular, но Vue не делает этого.
Давайте рассмотрим, как TypeScript используется в Vue2:
Если вы использовали TypeScript в Vue2, мы в основном знакомы с этими двумя решениями сообщества:vue-class-componentа такжеvue-property-decorator.
Обе схемы основаны наClassЕсли это реализовано, то Vue3 должен быть дружественным к типам.Поскольку есть два таких зрелых решения сообщества, оно будет продолжать использовать это направление в Vue3.Разве не просто разработать лучший API на основе класса?
Действительно, новые были реализованы даже на этапе прототипа Vue3.Class API, но позже этот API был удален. Потому что вода класса действительно слишком глубока.
Прежде всего, Class API опирается на такие предложения, как поля и декораторы, особенно предложения по декораторам действительно слишком много ям, мы можем взглянуть на githubTC39опредложение декораторовОбсуждение и прогресс:GitHub.com/Job39/предложения….
У этой штуки еще обсуждается 41 вопрос.Среди 167 вопросов, которые были закрыты, более интересен тот, что раньшеV8Команда напрямую отклонила одно из предложений декораторов по соображениям производительности.Пожилой мужчина прокомментировал ниже, что Цюцю не следует отменять предыдущее предложение из-за этого предложения, потому что многие люди в сообществе уже используют его, напримерEmber,Angular,Vueи т.п.
Сами декораторы пережили столь долгий период споров и несколько раз сильно менялись, но до сих пор остаются в тренде.stage2Сцена:
Что такое концепция stage2? Можно разместить в О программе на TC39Документациявидел в:
этап 2 означает, что вещи в этом предложении могут резко измениться в любой момент, по крайней мере, ввестиstage3Никаких разрушительных изменений в этапах не будет.
Итак, теперь декораторы в TS все еще можно использовать, потому чтоTSРеализация представляет собой более раннюю версию декораторов, которая не соответствует последним предложениям декораторов.В течение этого периода декораторы претерпели несколько серьезных изменений.
Кроме того, VueLoader, используемый вBabelРеализация декораторов иTSРеализация декораторов отличается, что может привести к некоторым из наиболее экстремальных случаев использования.
Итак, для классаСложностьа такжеНеопределенность, эта вещь пока не рассматривается в Vue3, а Class API не приносит другой практичности, кроме немного лучшей поддержки типов. Но для совместимости версий Vue3 такжепо-прежнему будет поддерживатьТолько что упомянутые две общественные программы. Итак, как вы можете использовать TypeScript после отказа от Class API?
На самом деле, сущность класса - это функция, поэтому основана на основеfunctionAPI также может быть дружественным к типам и может работать лучше, особенно параметры и возвращаемые значения в функции очень дружественны к системе типов, поэтому появился этот основанный на функциях API, который теперь является средним Vue3.Composition API.
3. Удовлетворить потребность в разработке крупномасштабных приложений
По мере того, как Vue становится все более популярным, разработкабольшой проектТребований становится все больше и больше.TypeScriptТакая система типа также должна быть в состоянииЧистая емкость для повторно используемого кода.
Умело, функциональноComposition API, также известный как составной API, решает все эти проблемы, молодец! Для Composition API я бы использовалтретья частьобсуждать дальше.
Как - как оптимизировать?
Что касается оптимизации, мы в основном говорим о двух аспектах:как быть быстрееа такжекак стать меньше.
Как быть быстрее?
- Object.defineProperty => Proxy
- прорватьVirtual DOMгорлышко бутылки
- Болееоптимизация во время компиляции
SlotКомпилируется в функции по умолчанию
Статический анализ шаблона генерирует разметку оптимизации VNode——patchFlag
Object.defineProperty => Proxy
Эта часть, о которой мы только что говорили, не только уменьшает объем памяти, но и ускоряет инициализацию компонента, так насколько быстро?
я переехалСтадия прототипа Vue3а такжеVue2.5Сравнительная таблица теста производительности при инициализации.Рендеринг 3000 экземпляров компонента с состоянием:
Как видите, объем памяти такой же, как у Vue2.половина, скорость инициализации почтиудвоенный.
Однако этого недостаточно!
Это просто инициализация, давайте посмотрим на компонентПри обновленииОптимизация.
Преодолеть узкое место виртуального DOM
Сначала рассмотрим традиционныеВиртуальное DOM-деревоКак обновляется:
При изменении данных два дерева vdom будутdiffСравните, найдите узел, который необходимо обновить, а затемpatchдля фактическогоDOMОбновите в браузер. Этот процесс был оптимизирован в Vue2 ккомпонентыОтрисовывая Watcher для точного поиска компонента, который необходимо обновить, сравните дерево vdom со всем компонентом. Оптимизация детализации этого компонентаReactЭто также было сделано, но эта операция оптимизации передана пользователю, например, использованиеpureComponeng,shouldComponentUpdateи т.п.
Но степень детализации компонентов относительно грубая, поэтому Vue3переписатьВиртуальный дом, чтобы воспользоватьсяСтатический анализ шаблоновпреимущество для дальнейшего сужения детализации обновления додинамический элементЧетноединамические свойства.
Сначала рассмотрим простейший случай:
Процесс сравнения в традиционном виртуальном DOM:
Мы видим, что в этом шаблоне структура всего узла компонентастабильный, и в нем много полностью статических узлов, и только текстовое содержимое одного узла является динамическим. При традиционном vdom он по-прежнему проходит через узлы diff, которые вообще не изменятся. Хотя Vue2 оптимизировал и пометил эти полностью статические узлы способом fastPath, чтобы пропустить различия этих статических узлов, все еще существует процесс обхода рекурсии.
Так как же будет выполняться сравнение в новой виртуальной DOM Vue3?
пройти черезcompilerСтатический анализ шаблонов, статический контент выполняется в оптимизированном режимеhosting, то есть статический узел продвигается наружу, а собственно генерацияvnodeтолько динамические элементы<p class="text">{{ msg }}</p>
, а затем проанализируйте, что может измениться в этом элементе, и отметьте этот элемент знакомpatchFlag, указывая, что этот элемент может изменитьсяТипыЯвляется ли текстовое содержимое textContent или классом класса атрибута и так далее.
Давайте посмотрим на компиляцию шаблонаrenderРезультат после функции:
можно увидеть,полностью статичныйЭлемент был переведен в функцию рендеринга, которая фактически создастvnodeСуществует только один элемент p с динамическим текстовым содержимым.
Таким образом, под новым виртуальным домом процесс этого компонента этого компонента становится:
На первый взгляд это оптимизация на порядок.
Итак, только что сказал, что это ситуация, когда структура узла компонента полностью фиксирована, тогда есть другая ситуация:динамический узел.
В шаблоне Vue единственная ситуация, когда появляются динамические узлы, этодва:
- v-if
- v-for
Первый взглядv-if:
Мы видим, что внутри v-if структура узла сноваполностью исправлено, и только{{ msg }}
является динамическим узлом. Итак, если вы разделите v-if наблокироватьЕсли да, то это становится ситуацией, которую мы видели в прошлый раз. Поэтому, пока весь шаблон сначала рассматривается как блок, а затем вложенные блоки разбиваются на динамические инструкции, каждый блок становится простейшим случаем:
И внутри каждого блокадинамический элементВсе, что нужно, это простая ничьямножествоПросто запишите след. Таким образом, процесс сравнения просто рекурсивно проходит, чтобы найти эти блоки с динамическими узлами, и процесс сравнения может быть завершен в соответствии с массивом этих динамических блоков.
Таким образом, новый процесс diff для примера v-if выглядит следующим образом:
v-for также использует тот же принцип, разделяя v-for на Блок:
только v-длядинамический узел, внутри каждого цикла v-for: только {{ item.message }} являются динамическими узлами. Его разностный процесс:
Суммировать:
- основывать шаблон наИнструкция динамического узланарезать в гнездоблокировать
- Структура узла внутри каждого блокафиксированныйиз
- Каждый блок должен начинаться только с одногоплоский массивотслеживать себядинамический узел
Таким образом, производительность обновления виртуального DOM изменяется сОбщий размер шаблонасвязанные, подняты только доколичество динамического контентаСвязанный:
Дополнительные оптимизации времени компиляции
-
SlotКомпилируется по умолчанию какфункция
Это позволяет использовать слоты между родительским и дочерним компонентами.обновить отношениябольше не связаны сильно
-
Используйте шаблоныстатический анализВведите теги, сгенерированные vnode -patchFlag
Мы только что упомянули об этом, посколькуpacthFlagОпределение , мы можем перейти к исходному коду, чтобы увидеть (для удобства скриншотов я удалил некоторые комментарии, и отметил двоичные значения первых нескольких типов):
<<— оператор сдвига влево, мы видим, что всего имеетсядесятьДинамическийТипы, значение каждого типа получается путем сдвига разных цифр на основе 1, поэтому одиннадцатизначноедвоичное числоописывает vnodeдинамический тип. И Юда очень любезно рассказал нам, как это использовать:
patchFlag vnode передается|Операторы комбинируются, используется patchFlag vnode и patchFlag, представленный конкретным типом&Оператор вычисляет, если полученный результат0, это означает, что атрибут этого типа этого vnodeне изменитсяиз,не 0, иначе. также привело вас кrenderer.ts
Давайте посмотрим, как его использовать, но, похоже, есть проблема с его путем... Что я вижу, так этоpackages/runtime-core/src/renderer.ts
. Но более подробное содержание здесь раскрываться не будет, если вам интересно, вы можете написать об этом статью в будущем.
Когда я увидел операцию You Da, я был просто в шоке: вы все еще можете писать такой код?
Тут на меня нахлынуло вдохновение, и я подумал о том, чтобы написатьАутентификация пользователяВроде так можно играть.
Итак, попробуйте сейчас:
Довольно интересно -
Ближе к дому, после таких слоев оптимизации, что же такое Vue3?как быстро?
Данные, предоставленные, когда я перехожу к выпуску vue3.0docs.Google.com/spreadsheet…Перевезено в:
Как видите, по сравнению с Vue2, Vue 3 имеет размер пакета41% снижение, первоначальный рендерингна 55% быстрее,продлитьна 133% быстрееи использование памяти54% снижение.
Как стать меньше?
Самое главное – использовать его в полной мере.Tree-shakingХарактеристики дерева, так что же такое Tree-shaking?Принцип работы:
маленькая шутка...
MDNОписание сотрясения дерева выше:
Что это значит? Чтобы лучше оценить его роль, давайте сначала рассмотрим дваexportзаписывается как:
Первый:
const msgA = 'hhhh'
const msgB = 777
const funcA = () => {
console.log('AAA')
}
const funcB = () => {
console.log('BBB')
}
export default{
msgA,
msgB,
funcA,
funcB
};
Второй:
export const msgA = 'hhhh'
export const msgB = 777
export const funcA = () => {
console.log('AAA')
}
export const funcB = () => {
console.log('BBB')
}
тогда яmain.ts
Внедрите и используйте эти два модуля соответственно в:
Первый:
import TreeShaking1 from "@/benchmarks/TreeShaking1"
console.log(TreeShaking1.msgA)
TreeShaking1.funcA()
Второй:
import {funcA,msgA} from "@/benchmarks/TreeShaking2"
console.log(msgA)
// funcA()
генерируется после сборкиapp.js bundle
:
Первый:
Второй:
Мы видим, что после встряхивания дерева импортируются только те, которые входят в комплект, ана самом деле будет использоватьсякодовый блок. Многие прогрессивные особенности в Vue3 переписаны, используя второй способ написания, а такжешаблонЭто также дружественно к тряске деревьев.
Но не все можно стряхнуть, есть части кода, которые незаменимы для любого типа приложений, мы называем эти незаменимые частиБазовый размер, поэтому, хотя Vue3 добавляет много новых функций, сжатый базовый размер составляет всего10KBили около того, даже меньше, чем Vue2половина.
Я положил проект там, где сейчас находятся две демонстрацииbuildпосле:
могу видеть этоapp.jsВ комплекте только9.68kb
, который по-прежнему включаетrouter
В том числе и в прошлом сборки Vue2 вообще в20+kbнад.
Из-за недостатка места остальная часть контента будет представлена вам в следующей статье.
【🚨Предупреждение 4D】 Удивительный Vue3 (Часть 2)
В следующей статье давайте посмотрим, что нам предлагает Vue3, на что стоит обратить внимание.Новая вещь(включает в себяПрекрасная демонстрация):
- Composition API
- Fragment
- Suspense
- TelePort
- createRenderer API
- Vite