автор:bingggиз Thunder Front End
Оригинальный адрес:Руководство по оптимизации производительности приложений Vue
БлагодаряОтзывчивая системаа такжевиртуальная система DOM, Vue может автоматически отслеживать зависимости данных в процессе рендеринга компонентов и точно знать, какой компонент необходимо повторно визуализировать при обновлении данных.После рендеринга он будет проходить через виртуальный DOM diff, прежде чем он будет фактически обновлен до DOM. Разработчики приложений VueОбычно не требуетсяПроведите дополнительную работу по оптимизации.
Однако на практике все еще могут возникать проблемы с производительностью.Далее будут представлены некоторые методы обнаружения и анализа проблем с производительностью приложений Vue и некоторые предложения по оптимизации.
Общее содержание состоит из трех частей:
- Как найти проблемы с производительностью приложения Vue
- Предложения по оптимизации производительности приложений Vue во время выполнения
- Предложения по оптимизации производительности загрузки приложения Vue
1. Как найти проблемы с производительностью приложения Vue
Проблемы производительности приложений Vue можно разделить на две части: первая часть — это проблема производительности во время выполнения, а вторая — проблема производительности при загрузке.
Как и другие веб-приложения, лучшим инструментом для выявления проблем с производительностью приложений Vue является Chrome Devtool.Инструмент производительности можно использовать для записи проблем с производительностью во время выполнения, таких как использование ЦП, использование памяти и FPS, в течение определенного периода времени, а инструмент сети может использоваться для анализа проблем с загрузкой, производительностью.
Например, на вкладке «Снизу вверх» инструмента «Производительность» мы можем увидеть самые трудоемкие операции за определенный период времени, что очень полезно для оптимизации использования ЦП и низкого FPS. происходит, и мы можем знать конкретную функцию.Время выполнения, после обнаружения узкого места, мы можем сделать некоторую целевую оптимизацию.
Для получения дополнительной информации о том, как использовать Chrome Devtool, см.Руководство по обнаружению проблем с производительностью с помощью Chrome Devtool
2. Предложения по оптимизации производительности приложений Vue во время выполнения
Производительность во время выполнения в основном зависит от занятости ЦП, памяти, локального хранилища и других ресурсов после инициализации приложения Vue, а также своевременного реагирования на действия пользователя. Вот несколько полезных оптимизаций:
2.1 Введение файла Vue в производственную среду
В среде разработки Vue предоставляет множество предупреждений, которые помогут вам справиться с распространенными ошибками и ловушками. В производственной среде эти предупреждения бесполезны, но увеличивают размер приложения. Некоторые проверки предупреждений и некоторые мелкиенакладные расходы времени выполнения.
При использовании инструмента сборки, такого как webpack или Browserify, исходный код Vue будет решать, включать ли режим рабочей среды в соответствии с process.env.NODE_ENV, который по умолчанию является режимом среды разработки. Как в webpack, так и в Browserify есть методы для переопределения этой переменной, чтобы включить режим рабочей среды Vue, и предупреждение также будет удалено инструментом минимизации во время процесса сборки.
Для получения подробной информации см.Развертывание производственной среды
2.2 Прекомпилировать шаблоны с однофайловыми компонентами
При использовании шаблона в DOM или строкового шаблона в JavaScript шаблон будетСреда выполнения скомпилирована в функцию рендеринга. Обычно этот процесс протекает достаточно быстро, ноПриложения, чувствительные к производительности, лучше избегать этого использования..
Самый простой способ прекомпилировать шаблоны — использоватькомпонент одного файла- Соответствующие настройки сборки автоматически позаботятся о предварительной компиляции, поэтому встроенный код уже содержит скомпилированную функцию рендеринга вместо исходной строки шаблона.
Для получения подробной информации см.Предварительно скомпилированные шаблоны
2.3 Извлеките CSS компонента в отдельный файл
При использовании однофайлового компонента CSS внутри компонента начинается с<style>
теги вводятся динамически через JavaScript. Есть небольшиенакладные расходы времени выполнения, извлечение CSS для всех компонентов в один файл позволяет избежать этой проблемы, а также улучшает сжатие и кэширование CSS.
Обратитесь к соответствующей документации для этого инструмента сборки, чтобы узнать больше:
-
webpack + vue-loader (
vue-cli
Шаблон веб-пакета предварительно настроен) - Browserify + vueify
- Rollup + rollup-plugin-vue
2.4 ИспользованиеObject.freeze()
Повысить производительность
Object.freeze()
Вы можете заморозить объект.После заморозки вы не можете добавлять к объекту новые свойства, изменять значения его существующих свойств, удалять существующие свойства и изменять перечисляемость, конфигурируемость и конфигурируемость существующих свойств объекта. Этот метод возвращает замороженный объект.
Когда вы передаете простой объект JavaScript экземпляру Vuedata
вариант, Vue будет перебирать все свойства этого объекта и использоватьObject.definePropertyПревратите все эти свойства в геттеры/сеттеры.Эти геттеры/сеттеры невидимы для пользователя, но внутренне они позволяют Vue отслеживать зависимости и уведомлять об изменениях при доступе к свойствам и их изменении.
Но Vue сталкивается с чем-то вродеObject.freeze()
Если для этого параметра задано свойство объекта, которое нельзя настроить, методы перехвата данных, такие как setter getter, не будут добавлены к объекту.Обратитесь к исходному коду Vue.
Исходный код наблюдателя Vue
2.4.1 Сравнение эффектов повышения производительности
на основе Vuebig table benchmark, вы можете видеть, что при рендеринге таблицы 1000 x 10 включитеObject.freeze()
Сравнение до и после повторного рендеринга.
big table benchmark
Перед включением оптимизации
После включения оптимизации
В этом примереиспользовалObject.freeze()
в 4 раза быстрее, чем не использовать
2.4.2 ПочемуObject.freeze()
производительность будет лучше
Не используйтеObject.freeze()
Накладные расходы процессора
использоватьObject.freeze()
Накладные расходы процессора
Из сравнения видно, что использованиеObject.freeze()
После этого накладные расходы наблюдателя уменьшаются.
2.4.3 Object.freeze()
Сценарии применения
из-заObject.freeze()
Это заморозит объект, поэтому он больше подходит для сцены класса отображения.Если ваши атрибуты данных нужно изменить, вы можете заменить его на новый.Object.freeze()
Объект.
2.5 Структура данных Flatten Store
Много раз мы обнаружим, что информация, возвращаемая интерфейсом, представляет собой следующую глубоко вложенную древовидную структуру:
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
Если такая структура хранится непосредственно в хранилище, если мы хотим изменить информацию комментатора, нам нужно пройти слой за слоем, чтобы найти информацию о пользователе.В то же время возможно, что информация о пользователе появилась много время и другие места должны быть пройдены.Информация о пользователе также изменяется, и каждый процесс обхода будет приводить к дополнительным накладным расходам производительности.
Предположим, мы единообразно храним информацию о пользователе в магазине какusers[id]
При такой структуре стоимость модификации и чтения пользовательской информации становится очень низкой.
Вы можете вручную хранить информацию в интерфейсе с помощью таблицы, подобной этой, или вы можете использовать некоторые инструменты.Здесь мы должны упомянуть концепцию, называемуюJSON数据规范化(normalize)
, Normalizr — это инструмент с открытым исходным кодом, который может преобразовывать вышеупомянутые глубоко вложенные объекты JSON в объекты, представленные сущностями, используя идентификатор в качестве словаря через определенную схему.
Например, для приведенных выше данных JSON мы определяемusers
comments
articles
Три схемы:
import {normalize, schema} from 'normalizr';
// 定义 users schema
const user = new schema.Entity('users');
// 定义 comments schema
const comment = new schema.Entity('comments', {
commenter: user,
});
// 定义 articles schema
const article = new schema.Entity('articles', {
author: user,
comments: [comment],
});
const normalizedData = normalize(originalData, article);
После нормализации мы можем получить следующие данные.В таком виде мы можем хранить их в хранилище.После этого становится очень эффективно модифицировать и читать информацию о пользователе определенного идентификатора, а временная сложность снижается до O(1) .
{
result: "123",
entities: {
"articles": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: [ "324" ]
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
}
}
Для получения дополнительной информации обратитесь к документации normalizr.GitHub.com/Paul проникновение руки RO…
2.6 Избегайте проблем с производительностью, вызванных постоянными данными Store
Если вам нужно сделать приложение Vue доступным в автономном режиме или выполнить аварийное восстановление при сбое интерфейса, вы можете сохранить данные Store.В настоящее время вам необходимо обратить внимание на следующие аспекты:
2.6.1 Проблемы с производительностью при записи данных во время персистентности
Популярное в сообществе Vue vuex-persistedstate использует механизм подписки магазина для подписки на мутацию данных магазина. Если есть изменение, оно будет записано в хранилище. По умолчанию в качестве постоянного хранилища используется localstorage.
То есть по умолчанию каждый коммит будет записывать данные в localstorage. Localstorage записывается синхронно, и возникает много накладных расходов.Если вы хотите создать приложение со скоростью 60 кадров в секунду, вы должны избегать частой записи постоянных данных.
На снимке экрана, снятом инструментом Performance в среде разработки, видно, что происходит 6-секундная заморозка:
6 секунд отставания
Через Bottom-Up вы можете видеть, что setState занимает 3241,4 мс времени выполнения ЦП, а setState записывает данные в хранилище.
Исходный код vuex-persistedstate setState
Мы должны минимизировать частоту записи напрямую в Storage:
- Объедините несколько операций записи в одну, например, сначала используйте регулирование функции или кэширование данных в памяти, а затем запишите их вместе в конце.
- Пишите только при необходимости, например, только при изменении данных соответствующего модуля.
2.6.2 Избегайте постоянного роста емкости хранилища
Из-за ограниченной емкости постоянного кеша, например, кеш локального хранилища составляет всего 5 МБ в некоторых браузерах, мы не можем хранить все данные без ограничений, поэтому легко достичь предела емкости, и когда данные слишком велики, Операции чтения и записи добавят некоторую нагрузку на производительность, а также увеличится объем памяти.
Особенно после нормализации и выравнивания данных API часть данных будет разбросана по разным сущностям, а новые данные будут разбросаны по разным сущностям в следующий раз, что приведет к постоянному росту хранилища.
Следовательно, при разработке стратегии постоянного кэширования данных следует одновременно разработать стратегию очистки кэша для старых данных, например очистку старых объектов по одному при запросе новых данных.
2.7 Оптимизация производительности бесконечного списка
Если в вашем приложении очень длинные или бесконечные списки прокрутки, используйтеоконныйтехнологии для оптимизации производительности, требуется только рендерить небольшую область контента, сокращая время на повторный рендеринг компонентов и создание узлов dom.
vue-virtual-scroll-listа такжеvue-virtual-scrollerОба являются проектами с открытым исходным кодом, которые решают такого рода проблемы. Вы также можете обратиться к статье Google EngineerComplexities of an Infinite ScrollerДавайте попробуем реализовать виртуальный список прокрутки самостоятельно, чтобы оптимизировать производительность.Основные используемые методы — это переработка DOM, элементы надгробий и привязка прокрутки.
Дизайн бесконечного списка, нарисованный инженерами Google
2.8 Оптимизировать начальную производительность рендеринга сверхдлинного контента приложения за счет ленивой загрузки компонентов
Упомянутый выше сценарий с бесконечным списком больше подходит для ситуации, когда элементы в списке очень похожи, но иногда содержимое в сверхдлинном списке вашего приложения Vue часто отличается, например, в основном интерфейсе приложения. сложное приложение. Весь основной интерфейс состоит из множества различных модулей, и пользователи часто видят только один или два модуля в верхней части экрана. Модули в невидимых областях также выполняются и визуализируются во время первоначального рендеринга, что приводит к дополнительным потерям производительности.
Использование ленивой загрузки компонентов требует только рендеринга скелетного экрана, когда он не виден, нет необходимости фактически рендерить компоненты
Вы можете лениво загружать компонент напрямую.Для содержимого компонента в невидимой области он не загружается и не инициализируется напрямую, что позволяет избежать накладных расходов на инициализацию среды выполнения рендеринга. Для получения дополнительной информации, пожалуйста, обратитесь к нашей предыдущей статье в колонкеЛенивая загрузка компонентов для оптимизации производительности: введение в Vue Lazy Component, чтобы узнать, как добиться отложенной загрузки с детализацией компонентов.
3. Предложения по оптимизации производительности загрузки приложения Vue
3.1 Используйте рендеринг на стороне сервера (SSR) и предварительный рендеринг (Prerender) для оптимизации производительности загрузки
В одностраничном приложении часто имеется только один HTML-файл, а затем соответствующий сценарий маршрутизации сопоставляется в соответствии с полученным URL-адресом для динамического отображения содержимого страницы. Самая большая проблема с одностраничными приложениями заключается в том, что первый экран виден слишком долго.
Одностраничное приложение будет отправлять несколько запросов на отображение страницы, получать html-ресурс в первый раз, а затем получать данные через запрос, а затем отображать данные на странице. Более того, из-за существования текущей микросервисной архитектуры по-прежнему можно выдавать несколько запросов данных для рендеринга веб-страницы, и каждый запрос данных будет генерировать RTT (задержка приема-передачи), что приведет к длительной задержке загрузки. страница.
Сравнение рендеринга на стороне сервера, предварительного рендеринга и рендеринга на стороне клиента
В этом случае для повышения производительности загрузки можно использовать рендеринг на стороне сервера (SSR) и предварительный рендеринг (Prerender).В этих двух схемах пользователь читает непосредственно содержимое веб-страницы, что значительно экономит RTT ( задержка туда и обратно) из-за less. , и в то же время вы также можете встроить некоторые ресурсы в страницу, что может еще больше повысить производительность загрузки.
Вы можете обратиться к нашей колонке статьиНаправление оптимизации: руководство по предварительному рендерингу одностраничного приложения с несколькими маршрутами.Узнайте, как оптимизировать с помощью предварительного рендеринга.
Рендеринг на стороне сервера (SSR) может рассмотреть возможность использования Nuxt или следовать официальному руководству Vue.Руководство по Vue SSRДавайте строить шаг за шагом.
3.2 Оптимизация производительности загрузки сверхдлинного содержимого приложения за счет ленивой загрузки компонентов
В упомянутом выше сценарии со сверхдлинным содержимым приложения производительность начального рендеринга можно оптимизировать с помощью схемы ленивой загрузки компонентов, что также очень полезно для оптимизации производительности загрузки приложения.
Ленивая загрузка с детализацией компонентов в сочетании с асинхронными компонентами и фрагментацией кода веб-пакета может гарантировать загрузку компонентов по запросу, а также зависимых от компонентов ресурсов, запросов интерфейса и т. д. По сравнению с обычной ленивой загрузкой изображений, она также достигается по запросу. загрузка ресурса.
Водопадная диаграмма запросов до ленивой загрузки с компонентами
Запрос каскадной диаграммы после использования отложенной загрузки компонента
Использование схемы отложенной загрузки компонентов очень полезно для инициализации приложения и рендеринга сверхдлинного контента, что может уменьшить большое количество необходимых запросов ресурсов и сократить путь ключа рендеринга.Подробности см. в нашей предыдущей статье.Ленивая загрузка компонентов для оптимизации производительности: введение в Vue Lazy Component.
Суммировать
В этой статье приведены некоторые меры по оптимизации производительности во время выполнения и загрузки приложений Vue. Вот обзор и резюме:
-
Меры по оптимизации производительности приложений Vue во время выполнения
- Файлы Vue, импортированные в производственную среду
- Прекомпилировать шаблоны с однофайловыми компонентами
- Извлечь CSS компонента в отдельные файлы
- использовать
Object.freeze()
Повысить производительность - Выравнивание структуры данных Store
- Разумное использование данных постоянного хранилища
- Ленивая загрузка компонента
-
Меры по оптимизации производительности загрузки приложения Vue
- Рендеринг на стороне сервера/предварительный рендеринг
- Ленивая загрузка компонента
Конечно, эти методы оптимизации производительности, обобщенные в этой статье, не могут охватить все проблемы с производительностью приложений Vue.Мы также продолжим обобщать и дополнять другие проблемы и меры по оптимизации.Я надеюсь, что практический опыт, упомянутый в статье, может принести вам небольшое количество Работа по оптимизации производительности приложения Vue Небольшая помощь.