предисловие
Сегодня около 3:30 утра Ю Юйси опубликовал статью в своем Weibo. Конечно, босс находится в другом часовом поясе, наше раннее утро соответствует полудню часового пояса, где эпидемия была самой сильной.
Оригинальная ссылка:increment.com/frontend/лошадь…
Уроки, извлеченные из рефакторинга новой версии Vue.js
В прошлом году,VueКоманда занималась исследованиемVue.jsСледующий крупный релиз, который мы надеемся выпустить в первой половине 2020 года. (На момент написания эта работа все еще продолжается).VueОсновная версия была сформирована в конце 2018 года, когдаVue 2кодовой базе два с половиной года. Это может показаться недолгим в жизненном цикле универсального программного обеспечения, но за это время интерфейсная среда сильно изменилась.
Есть два основных соображения, которые привели нас к разработкеVueновая основная версия (и переписывает ее): во-первых, основные браузеры обычно предоставляют новыеJavaScriptЯзыковые функции. Во-вторых, со временем дизайн и архитектура текущей кодовой базы постепенно выставлены.
Зачем проводить рефакторинг
Воспользуйтесь преимуществами новых языковых возможностей
вместе сES6стандартизация, JavaScript (официально известный какECMAScript, сокращенно ES) получил значительные улучшения, и основные браузеры, наконец, начинают обеспечивать достойную поддержку этих новых функций. В частности, некоторые новые функции дают нам большое улучшениеVueфункциональные возможности.
Наиболее заметными из них являютсяProxy, что позволяет фреймворку перехватывать операции над объектами.VueОсновная функциональность — это возможность прослушивать изменения, внесенные в определяемое пользователем состояние, и обновления, управляемые данными.DOMСпособность.Vue 2используяgetterа такжеsetterЗамените свойства объекта состояния, чтобы реализовать эту возможность. переключиться наProxyзаставит нас устранитьVueсуществующие ограничения, такие как невозможность обнаружения добавления новых свойств и повышения производительности.
но,Proxyявляется особенностью самого языка и не может быть полностью реализована в старых браузерах.polyfill. Мы знали, что для того, чтобы воспользоваться этим преимуществом, нам нужно настроить диапазон поддержки браузеров фреймворком, что является крупным прорывом, который может быть выпущен только в новой основной версии.
Решить архитектурные проблемы
Решение этих проблем в текущей кодовой базе потребует много рискованного рефакторинга, почти эквивалентного полному переписыванию.
на техобслуживанииVue 2В процессе, из-за ограничений существующей архитектуры, у нас накопилось много проблем, которые трудно решить. Например, компиляторы шаблонов написаны таким образом, что поддержка исходной карты очень затруднена. Аналогично, хотяVue 2Технически позволяет строить для не-DOMРендерер для платформы, но нам пришлось разветвить кодовую базу и скопировать много кода, чтобы это произошло. Решение этих проблем в текущей кодовой базе потребует много рискованного рефакторинга, почти эквивалентного полному переписыванию.
При этом у нас накопились подводные камни в виде неявной связи между внутренностями различных модулей и плавающим кодом, который вроде бы никуда не годится. Это затрудняет понимание отдельных частей кодовой базы, и мы заметили, что участники редко чувствуют себя уверенно в отношении важных изменений. Рефакторинг даст нам возможность переосмыслить организацию кода в свете этих соображений.
начальная стадия прототипа
Мы начали в конце 2018 годаVue 3Прототип с первоначальной целью проверки решений этих проблем. На данном этапе мы в основном закладываем прочный фундамент для дальнейшего развития.
Переключиться на TypeScript
Vue 2изначально использовали чистыйJSнаписано. Вскоре после этапа прототипирования мы поняли, что система типов будет очень полезна для проекта такого размера. Проверка типов значительно снижает вероятность появления неожиданных ошибок во время рефакторинга и помогает участникам с большей уверенностью вносить важные изменения. мы проходимFacebookизFlowПроверка типов, так как она может быть постепенно добавлена к существующимJSпроект.FlowЭто помогает в какой-то степени, но мы не получаем многого от этого. Особенно меняющиеся требования делают обновление болезненным. а такжеTypeScriptа такжеVisual Studio CodeПо сравнению с глубокой интеграциейFlowДля интегрированной среды разработки (IDE) поддержка тоже не идеальна.
Мы также заметили, что пользователи все чаще используют обаVueа такжеTypeScript. Чтобы поддерживать их варианты использования, мы должны создавать и поддерживать отдельно от использования другой системы типов.TypeScriptутверждение. переключиться наTypeScripПозволит нам автоматически генерировать файлы объявлений, уменьшая нагрузку на техническое обслуживание.
Отдельная внутренняя упаковка
Мы также принялиmonorepo, где фреймворк состоит из внутренних пакетов, каждый со своим отдельнымAPI, определения типов и тесты. Мы хотим сделать зависимости между этими модулями более явными, чтобы разработчикам было легче читать, понимать и вносить все изменения. Это является ключом к нашим усилиям по снижению барьера для участия в проекте и улучшению его долгосрочной ремонтопригодности.
Настройка процесса RFC
К концу 2018 года у нас была новая система просмотра, управляемая данными, и виртуальныйDOMРабочий прототип рендерера. Мы проверили внутренние архитектурные улучшения, которые хотим внести, но включаем только общедоступныеAPIИзмененный черновик. Настало время превратить их в конкретные конструкции.
Мы знаем, что должны сделать это заранее и осторожно.VueШирокое использование означает, что критические изменения могут привести к значительным затратам на миграцию пользователей и потенциальной фрагментации экосистемы. Чтобы пользователи могли оставлять отзывы о критических изменениях, в начале 2019 года мы принялиRFC(запрос комментариев) процесс. каждыйRFCСледуйте шаблону, который фокусируется на мотивации, деталях дизайна, компромиссах и стратегиях внедрения. Поскольку этот процессGitHubВ репозитории предложения подаются как пулл-реквесты, поэтому обсуждение естественно разворачивается в комментариях.
ДолженRFCЭтот процесс оказался чрезвычайно полезным в качестве основы для размышлений, которая заставляет нас полностью учитывать все аспекты потенциальных изменений, вовлекать наше сообщество в процесс проектирования и отправлять хорошо продуманные запросы функций.
быстрее и меньше
Производительность имеет решающее значение для интерфейсных фреймворков. несмотря на то чтоVue 2Имеет отличную производительность, но рефакторинг дает возможность пойти дальше, экспериментируя с новыми стратегиями рендеринга.
Преодолеть узкое место виртуального DOM
Vueобладает довольно уникальной презентационной стратегией: он предоставляет что-то вродеHTMLсинтаксис шаблона, но компилирует шаблон для возврата виртуальногоDOMФункция рендеринга дерева. Фреймворк рекурсивно проходит два виртуальныхDOMдерево и сравнить каждый атрибут на каждом узле, чтобы определить фактическоеDOMкакие части нужно обновить. из-за современногоJavaScriptДвижок выполняет расширенную оптимизацию, поэтому этот довольно жестокий алгоритм обычно работает быстро, но все же включает много ненужных операций.CPUРабота. При просмотре большого количества статического контента с небольшим количеством динамических привязок (весь виртуальныйDOM) неэффективно, особенно если небольшое изменение требует рекурсии всего виртуальногоDOMдерево, чтобы увидеть, что изменилось.
К счастью, этап компиляции шаблона дает нам возможность выполнить статический анализ шаблона и извлечь информацию о динамических частях.Vue 2В некоторой степени это делается за счет пропуска статических поддеревьев, но более сложные оптимизации трудно реализовать из-за чрезмерно упрощенной архитектуры компилятора. существуетVue 3, мы используем соответствующийASTКонвейер преобразования переписывает компилятор, что позволяет нам писать оптимизации времени компиляции в виде подключаемых модулей преобразования.
С новой архитектурой мы хотели найти стратегию рендеринга, которая максимально уменьшила бы накладные расходы. Один из вариантов — отказаться от виртуальногоDOMи напрямую генерировать императивDOMоперации, но это устранило бы непосредственное написание манекенаDOMВозможность отображать функции, которые мы нашли очень ценными для опытных пользователей и авторов библиотек. Кроме того, это было бы огромным переломным моментом.
Во-вторых, лучший способ — избавиться от ненужных пустышек.DOMОбход дерева и сравнение атрибутов, которые, как правило, имеют наибольшую нагрузку на производительность во время обновлений. Для этого компилятор и среда выполнения должны работать вместе: компилятор анализирует шаблон и генерирует код с подсказками по оптимизации, а среда выполнения улавливает подсказки и по возможности выбирает более быстрый путь. Здесь есть три основных усилия по оптимизации:
Во-первых, на уровне дерева отметим, что структура узла полностью статична при отсутствии директив шаблона (например,v-ifа такжеv-for). Если разделить шаблон на динамический и статический"块", структура узла внутри каждого блока снова становится полностью статической. Когда мы обновляем узел внутри блока, нам больше не нужно рекурсивно перемещаться по дереву, поскольку мы можем отслеживать динамические привязки внутри этого блока в плоском массиве. количество обхода дерева, которое нам нужно выполнить на порядок, экономя виртуальныеDOMбольшая часть стоимости.
Во-вторых, компилятор активно обнаруживает статические узлы, поддеревья и даже объекты данных в шаблонах и продвигает их вrenderвне функции. Это позволяет избежать повторного создания этих объектов при каждом рендеринге, значительно улучшая использование памяти и снижая частоту сборки мусора.
В-третьих, на уровне элемента компилятор также генерирует флаг оптимизации для каждого элемента с динамическими привязками в зависимости от типа обновления, которое необходимо выполнить. Например, элементы с динамической привязкой класса и многими статическими свойствами получат флаг, указывающий, что требуется только проверка класса. Среда выполнения уловит эти подсказки и выберет выделенный быстрый путь.
В совокупности эти методы значительно улучшили наши обновления рендеринга, запустивVue 3Иногда даже больше, чемVue 2В десять раз быстрее.
очень маленький размер
Размер рамы также влияет на ее производительность. ЭтоWebВажная проблема для приложений, так как ресурсы должны загружаться динамически, а необходимый парсинг в браузереJavaScriptРаньше приложение было интерактивным. Особенно это касается одностраничных приложений. несмотря на то чтоVueвсегда был относительно легким(Vue 2Время выполнения сжимается до 23 кБ), но мы заметили два вопроса:
Во-первых, не все используют все возможности фреймворка. Например, приложения, которые никогда не используют компоненты перехода, все равно будут загружать код, связанный с переходом, и тратить время на его синтаксический анализ.
Во-вторых, фреймворк бесконечно расширяется по мере того, как мы добавляем новые функции. Когда мы думаем о добавлении новых функций, мы должны учитывать вопрос размера. Поэтому мы предпочитаем фреймворки, которые включают в себя только ту функциональность, которую будет использовать большинство пользователей.
В идеале пользователи должны иметь возможность удалять код неиспользуемых функций платформы во время сборки, также известный как ""Tree Shaking" — упаковывайте только тот код, который они используют. Это также позволит нам выпускать функции, которые часть пользователей сочтет полезными, не увеличивая фактическую стоимость загрузки для остальных.
существуетVue 3, мы проходим большую часть глобальногоAPIи внутренний помощник перемещен вESЭкспорт модуля для достижения этой цели. Это позволяет современным инструментам упаковки статически анализировать зависимости модулей и удалять код, связанный с неиспользуемыми экспортами. Компилятор шаблона также генерируетTree ShakingДружественный код, который импортирует вспомогательную функцию только в том случае, если функция действительно используется в шаблоне.
Некоторые части кадра никогда неTree Shaking, так как они необходимы для любого приложения. Мы называем метрики этих существенных частей базовым размером. Несмотря на то, что было добавлено много новых функций,Vue 3базовый размерgzipПосле всего около 10 КБ, даже неVue 2
VueVueVueБлагодаря более широкому внедрению мы узнаем больше о требованиях проектов, содержащих сотни модулей и поддерживаемых десятками разработчиков с течением времени. Для таких типов проектов, какTypeScriptТакая система типов и возможность повторного использования кода имеют решающее значение.Vue 2Поддержка в этих областях не идеальна.
в дизайнеVue 3На ранних этапах мы пытались улучшить, обеспечив встроенную поддержку написания компонентов с использованием классов.TypeScriptинтегрированный. Задача заключается в том, что нам нужно сделать много языковых функций (таких как класс и декораторы) и официально официальноJavaScriptНекоторые, возможно, изменились раньше. Связанные с этим сложность и неопределенность заставляют нас подозревать, что добавлениеClass APIДействительно ли это разумно, потому что обеспечивает лучшееTypeScriptНикаких дополнительных функций, кроме интеграции, не предусмотрено.
Мы решили исследовать другие подходы к проблеме масштабирования. полученоReact HooksВдохновленные , мы рассмотрели возможность предоставления основанных на данных представлений нижнего уровня и жизненных циклов компонентов.API, чтобы реализовать более свободный способ написания логики компонентов, называемыйComposition API. Вместо того, чтобы определять компоненты, указывая длинный список опций,Composition APIПозволяет пользователям выражать, писать и повторно использовать логику компонентов с отслеживанием состояния так же свободно, как они пишут функции, обеспечивая при этом превосходное качество.TypeScriptслужба поддержки.
Мы очень рады этой идее. несмотря на то чтоComposition APIОн предназначен для решения определенного класса задач, но технически доступен только при написании компонентов. В первом проекте этого предложения мы намекнули, что, возможно, добавим существующийOptions APIзаменитьComposition API. Это вызвало большое недовольство среди членов сообщества, что преподало нам ценный урок четкого изложения долгосрочных планов и намерений, а также понимания потребностей пользователей. Выслушав отзывы нашего сообщества, мы полностью переработали предложение, чтобы было ясно, чтоComposition APIбыло бы правильноOptions APIдобавка. Получение пересмотренного предложения было более позитивным, и было получено много конструктивных предложений.
установление
существуетVueИз более чем миллиона разработчиков есть толькоHTMLа такжеCSSОсновы для начинающих, отjQueryЕсть старые программисты, мигрирующие, есть фронтенды, мигрирующие с другого фреймворка, есть даже инженеры по бэкенду, которые ищут решения для фронтенда, и архитекторы программного обеспечения, которые имеют дело с программным обеспечением в масштабе. Некоторым разработчикам может потребоваться добавить интерактивности в устаревшие приложения, в то время как другим могут потребоваться разовые проекты с гибкой разработкой, но с ограниченными потребностями в обслуживании. Возможно, вам придется иметь дело с крупными многолетними проектами и меняющейся командой разработчиков на протяжении всего жизненного цикла проекта.
Поскольку мы стремимся сбалансировать различные компромиссы,VueКонструкции постоянно влияют и вдохновлены этими потребностями.VueИзвестный как "渐进式框架», который инкапсулирует слои, полученные в результате этого процесса.APIдизайн. Новички могут использоватьCDNсценарий, основанный наHTMLшаблоны и интуитивно понятныйOptions APIлегко учиться, в то время как эксперты могут использовать полнофункциональныйCLI, Рендеринг иComposition APIдля работы с более сложными проектами.
Многое еще предстоит сделать, чтобы реализовать наше видение. Самое главное, обновите окружающие библиотеки, документацию и инструменты, чтобы обеспечить плавную миграцию. Мы продолжим усердно работать в течение следующих нескольких месяцев, и нам не терпится увидеть, что сделает сообщество черезVue 3Создайте что-нибудь.
Замечательные статьи в прошлом
- «Vite наконец выпустил китайские документы! Сообщество Svelte полностью интегрировано"
- «Создайте собственную визуальную карту данных, не полагаясь на какую-либо библиотеку»
- «Супер забавная новая функция Vue: введение переменных JS в CSS»
- 《整治GitHub不文明现象!微软推出评论区! 》
- Vue 3.0.3: новая передача переменных CSS и последнее предложение REF
- «Двойной 11 маленький черный ящик — это очень круто? Давайте улучшим его с помощью переменных CSS! 》
- «Не стоит недооценивать Цзюгунге, один вопрос может раскрыть истинную форму кандидата! 》
- «Вопросы на собеседовании по макету мобильного терминала всесторонне изучают ваши навыки CSS (в центре)»
- «Серия запутанных действий после установки объекта-прототипа на прокси»
- «Супер забавная новая функция Vue: портал DOM»
- «Использование суперпопулярной библиотеки React CSS-in-JS в проектах Vue: стилизованные компоненты»
- «Наконец-то настала очередь Vue вдохновлять React? 》
- «Небольшая яма Vue3 под IOS»
- «Оптимизируйте свой проект React с помощью immer вместо immutable в 2020 году»
- «Допрос души от «Бога Троицы», автор буклета «React Hooks and Immutable»
- "Использование хуков в новой версии vue-router"
- «[Перевод] React 17 наконец-то выпустила RC-версию, официальный представитель сказал, что 17 — это переходная версия! 》
- «Отец рефакторинга Node Deno наконец-то выпущен, заменит ли он в конечном итоге Node?» 》