Эта статья участвует в "Боевой рекорд оптимизации производительности» Тема Призыв к докладам
Всем привет, меня зовут Шаньюэ.
Мы разделяем направление оптимизации производительности на следующие два аспекта, которые полезны для структурированного мышления и системного анализа.
- Загрузка производительности. Способы более быстрой загрузки ресурсов с сервера в браузер, такие как различные оптимизации http и объема ресурсов, направлены на повышение производительности загрузки.
- производительность рендеринга. Как быстрее отображать ресурсы в браузере. Такие как сокращение перестановки и перерисовки, rIC и т. д., все они направлены на повышение производительности рендеринга.
Основные показатели производительности и API производительности
- LCP: производительность загрузки. Отрисовка максимального содержимого должна быть выполнена в течение 2,5 с.
- FID: Интерактивное представление. Первая задержка ввода должна завершиться в течение 100 мс.
- CLS: Стабильность страницы. Совокупное смещение компоновки, которое необходимо рассчитать вручную, CLS должно быть ниже 0,1.
Рассчитать и собрать
При сборе основных показателей эффективности каждого пользователя на стороне браузера можно использоватьweb-vitals
собрал и прошелsendBeaconСообщить в систему RBI.
import { getCLS, getFID, getLCP } from 'web-vitals'
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
navigator.sendBeacon('/analytics', body))
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);
Более быстрая доставка: CDN
Распределение ресурсов по граничным сетевым узлам CDN позволяет пользователям получать желаемый контент поблизости, значительно сокращая расстояние передачи по оптическому волокну, что позволяет пользователям со всего мира иметь хороший опыт работы в сети при открытии веб-сайтов.
Быстрая передача: http2
http2
Многие его характеристики определяют его более высокую скорость передачи.
- Мультиплексируя, браузер может отправлять N запросов параллельно.
- Сжатие заголовка, меньший объем полезной нагрузки.
- Приоритет запроса, более быстрые критические запросы
В настоящее время большинство веб-сайтов находятся на http2, что можно просмотреть в панели консоли.
Поскольку http2 может запрашивать параллельно и решать проблему блокировки заголовка строки http1.1, следующие точки оптимизации производительности будут устаревшими.
- Консолидация ресурсов. как
https://shanyue.tech/assets??index.js,interview.js,report.js
- Шардинг домена.
- Изображение спрайта. Объединяйте бесчисленное количество маленьких картинок в одну большую.
Быстрая передача: воспользуйтесь кэшированием HTTP
Лучшая стратегия кэширования ресурсов может уменьшить количество обращений к источнику для CDN и количество запросов, отправляемых браузерами. Независимо от того, какой момент, он имеет лучший опыт посещения при втором посещении веб-сайта.
- стратегия кэширования
- Сильный кеш: упакованные ресурсы с хэш-значениями (например, /build/a3b4c8a8.js)
- Согласованный кеш: упакованные ресурсы без хеш-значения (например, /index.html)
- Разделение пакетов
- Избегайте модификации одной строки кода, которая делает недействительным весь кеш пакета.
Более быстрые передачи: уменьшите HTTP-запросы и нагрузку
Сжимайте и оптимизируйте ресурсы веб-сайта, чтобы уменьшить нагрузку на HTTP.
- js/css/image и другие обычные оптимизации объема ресурсов, это большая тема, а затем обсуждается отдельно ниже
- Оптимизация небольших изображений, встроенные небольшие изображения в качестве URI данных для уменьшения количества запросов.
- Ленивая загрузка изображения
- Новый API: IntersectionObserver API
- Новое свойство: загрузка=ленивый
Меньший размер: gzip/brotli
Это справедливо для текстовых ресурсов, таких как JS, CSS и HTML, но мало влияет на изображения.
-
gzip
Файл сжат алгоритмом LZ77 и кодировкой Хаффмана, чем больше повторений, тем больше места можно сжать. -
brotli
Сжатие файлов с помощью варианта алгоритма LZ77, кодирования Хаффмана и моделирования текста второго порядка, более продвинутого алгоритма сжатия, более высокой производительности и степени сжатия, чем gzip.
доступно в браузереContent-Encoding
Проверьте заголовок ответа, чтобы узнать, включен ли алгоритм сжатия на веб-сайте.В настоящее время полностью включены Zhihu, Nuggets и т. д.brotli
сжатие.
# Request Header
Accept-Encoding: gzip, deflate, br
# gzip
Content-Encoding: gzip
# gzip
Content-Encoding: br
Меньший размер: инструмент обфускации сжатия
TerserЭто артефакт сжатия и обфускации ресурсов Javascript.
Его можно сжать в соответствии со следующими стратегиями:
- Замените короткие переменные длинными именами переменных
- Удалить пробелы новой строки
- Предварительный расчет:
const a = 24 * 60 * 60 * 1000
->const a = 86400000
- Удалить код, который не может быть выполнен
- Удалить бесполезные переменные и функции
Доступны наTerser ReplПроверьте эффект сжатия кода онлайн.
-
swcэто еще один инструмент для сжатия Javascript, он имеет тот же
terser
тот же API, так как он созданrust
написано, поэтому он имеет более высокую производительность. - html-minifier-terserИнструменты для сжатия HTML
Меньший размер: меньший Javascript
Что касается меньшего Javascript, два из них были приведены выше:
- gzip/brotli
- terser (minify)
Есть и другие моменты, которые следует учитывать:
- Ленивая загрузка маршрутов, не нужно загружать ресурсы всего приложения
- Tree Shaking: бесполезный экспорт будет удален в производстве
- browserlist/babel: Своевременное обновление списка браузеров приведет к уменьшению размера прокладки.
Еще один вопрос:
Как проанализировать и оптимизировать объем Javascript текущего проекта? При использованииwebpack
Это намного проще.
- использовать
webpack-bundle-analyze
Анализ упакованного объема - Замените некоторые библиотеки меньшими, такими как moment -> dayjs
- Загрузка по требованию некоторых библиотек, таких как
import lodash
->import lodash/get
- Используйте поддержку Tree Shaking для некоторых библиотек, таких как
import lodash
->import lodash-es
Меньший размер: меньшее изображение
Теперь во фронтенд-разработке.webp
универсальный коэффициентjpeg/png
меньше, при этомavif
чемwebp
на один уровень ниже
Для полной совместимости опциональноpicture/source
откат
<picture>
<source srcset="img/photo.avif" type="image/avif">
<source srcset="img/photo.webp" type="image/webp">
<img src="img/photo.jpg" width="360" height="240">
</picture>
- Более подходящий размер: если на странице нужно отобразить только изображение размером 100 пикселей/100 пикселей, сожмите изображение до 100 пикселей/100 пикселей.
- Более подходящее сжатие: внешнее изображение может быть правильно сжато, например,
sharp
Ждать
Оптимизация рендеринга: критический путь рендеринга
Следующие пять шагов являются критическим путем рендеринга.
- HTML -> DOM, анализировать html в DOM
- CSS -> CSSOM, анализировать CSS в CSSOM
- DOM/CSSOM -> Дерево рендеринга, объединение DOM и CSSOM в дерево рендеринга
- RenderTree -> Layout, определите информацию о местоположении каждого узла в дереве рендеринга.
- Layout -> Paint для визуализации каждого узла в браузере
Оптимизация рендеринга в значительной степени связана с оптимизацией критического пути рендеринга.
preload/prefetch
preload
/prefetch
Приоритет HTTP можно контролировать, чтобы добиться более быстрого ответа на критические запросы.
<link rel="prefetch" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
- preload загружает ресурсы, необходимые для текущего маршрута, с высоким приоритетом. Как правило, выполняйте предварительную загрузку для ресурсов разделения пакетов и ресурсов разделения кода.
- prefetch имеет низкий приоритет и загружает ресурсы, когда браузер бездействует. Обычно он используется для загрузки других ресурсов маршрутизации. Например, когда ссылка появляется на странице, ресурсы маршрутизации текущей ссылки могут быть предварительно загружены. (next.js будет выполнять ленивую загрузку + предварительную выборку по ссылке по умолчанию, то есть, когда ссылка появляется на странице, она автоматически выполняет предварительную выборку ресурсов маршрутизации, на которые указывает ссылка
контрейлерныхdns-prefetch
, который предварительно разрешает DNS для адресов узлов.
<link rel="dns-prefetch" href="//shanyue.tech">
Оптимизация рендеринга: стабилизация и регулирование
- Anti-shake: чтобы предотвратить дрожание, триггер события будет сброшен в течение единицы времени, чтобы избежать многократного запуска события из-за случайной травмы. Реализация кода фокусируется на очистке clearTimeout. Антишейк можно сравнить с ожиданием лифта, пока входит один человек, ему нужно какое-то время подождать. Бизнес-сценарии имеют дублирующие отправки, чтобы избежать многократного нажатия кнопки входа.
- Регулирование: для управления потоком событие может запускаться только один раз в единицу времени, аналогично ограничению скорости на стороне сервера. Реализация кода фокусируется на разблокировке и закрытии блокировки timer=timeout; timer=null. Троттлинг можно сравнить с прохождением светофора, и вы можете пропускать батч каждый раз, когда ждете красный свет.
Будь то защита от сотрясения или дросселирование, оно может значительно сократить количество рендерингов, а также может использоваться в React.use-debounce
хуки, как избежать повторного рендеринга.
import React, { useState } from 'react';
import { useDebounce } from 'use-debounce';
export default function Input() {
const [text, setText] = useState('Hello');
// 一秒钟渲染一次,大大降低了重新渲染的频率
const [value] = useDebounce(text, 1000);
return (
<div>
<input
defaultValue={'Hello'}
onChange={(e) => {
setText(e.target.value);
}}
/>
<p>Actual value: {text}</p>
<p>Debounce value: {value}</p>
</div>
);
}
Оптимизация рендеринга: оптимизация виртуального списка
Это еще одна распространенная тема.Как правило, в окне просмотра поддерживается виртуальный список (отрисовывается только около дюжины фрагментов данных), и положение окна просмотра отслеживается для управления виртуальным списком в окне просмотра.
В React доступны следующие библиотеки:
Оптимизация рендеринга: кэширование запросов и ресурсов
В некоторых интерфейсных системах запрос отправляется при загрузке страницы, запрос повторно отправляется при переключении маршрута и обратно, а страница повторно отображается после завершения каждого запроса.
Однако в большинстве этих повторных запросов нет необходимости, и разумное кэширование API позволит достичь цели оптимизации рендеринга.
- Добавить ключ к каждому GET API
- Управлять кешем API по ключу, который будет получен из кеша при повторных запросах
function Example() {
// 设置缓存的 Key 为 Users:10086
const { isLoading, data } = useQuery(['users', userId], () => fetchUserById(userId))
}
Web Worker
Возьмите пример:
Как добиться высокой производительности компиляции и преобразования кода в реальном времени в чистых браузерах?
Если чистая фрагментация реализована с использованием традиционного Javascript, блокировка основного потока займет слишком много времени, что может привести к зависанию страницы.
При использованииWeb Worker
Гораздо эффективнее будет сделать это дополнительным потоком, в основном все функции компиляции кода на стороне браузера выполняетWeb Worker
выполнить.
WASM
- JS работает медленно
- С++/Rust высокая производительность
- Пишите код на C++/Rust и запускайте его на Javascript.
Возьмите пример:
Как добиться высокопроизводительного сжатия изображений в чистых браузерах?
В принципе, это труднодостижимо.Производительность и экологичность Javascript определяют сложность сжатия изображений.
С помощью WASM это эквивалентно заимствованию экологии других языков.
- libavif: библиотека декодирования и кодирования avif, написанная на языке C.
- libwebp: библиотека декодирования и кодирования webp, написанная на языке C.
- mozjpeg: Библиотека декодирования и кодирования JPEG, написанная на языке C.
- oxipng: библиотека оптимизации png, написанная на языке Rust
И благодаря WASM экология этих других языков может быть перенесена в браузер, чтобы реализовать высокопроизводительный инструмент сжатия изображений в автономном режиме.
Если вы хотите узнать об этом типе инструмента, см.squoosh