- PVSM.RU - https://www.pvsm.ru -
Какие-то приложения грузятся быстро, какие-то медленно, но за счет чего это происходит? Только ли скорость загрузки страницы является показателем производительности приложения?
Ответить на эти и многие другие вопросы в одной статье было бы очень сложно. Поэтому я собрал каталог ссылок и разбил его на категории. Но для начала — немного теории о том, что такое производительность и когда о ней стоит задуматься.
Вы можете годами разрабатывать веб-приложения и практически не сталкиваться с проблемами производительности приложений.
Но, вероятнее всего, проблемы возникают в следующих ситуациях:
Глобально проблемы с производительностью веб-приложений можно разделить на две категории: передача данных и runtime.
Каждая из этих категорий содержит в себе очень много нюансов, о которых мы часто не задумываемся, но которые отличают качественные приложения от некачественных.
Вот самые популярные метрики производительности веб-приложений (все должны быть минимальными):
Хоть TTFB и TTI и относятся к метрикам производительности загрузки страницы, на них могут влиять и проблемы, связанные с runtime.
Основным набором инструментов в арсенале разработчика является Chrome DevTools [5] или аналогичные инструменты, например Firebug/Firefox developer tools [6].
Про них можно писать отдельные статьи, но мы ограничимся самыми важными моментами.
Network [7] — позволяет подробно проанализировать, какие ресурсы загружаются на странице, с каких ресурсов, с какой скоростью и так далее. Этот инструмент часто используется для ручного анализа скорости загрузки страницы.
Performance [8] — в этой вкладке можно включить запись вызовов исполнения кода, операций ввода/вывода и других. Помимо этого запись можно делать с эмуляцией троттлинга сети и CPU. Например, проверить работу приложения на слабых устройствах.
Lighthouse [9] — инструмент, встроенный в Chrome DevTools, который запускает загрузку страницы, записывает метрики, делает по ним анализ и даже выдает рекомендации по улучшению производительности.
Инструменты для мониторинга производительности веб-приложений можно разделить на две категории: те, что производят синтетические измерения и те, что записывают данные производительности с реальных пользователей.
Помимо этого есть инструменты наподобие Webpack-bundle-analyzer [13], которые нельзя отнести к этим двум категориям. Но с их помощью можно измерять некоторые параметры, которые влияют на производительность, например размер бандла.
TCP connection, DNS lookup [14] — ускорить загрузку страницы можно даже за счет правильной конфигурации подключений к серверу. В частности, если использовать DNS pre-fetching или даже IP-адреса вместо доменных имен.
TTFB (Time to First Byte) [15]. Время до получения первого байта — это важная метрика. Для ее ускорения нужно стараться реализовывать как можно меньше логики на сервере перед выдачей index.html.
HTTP1 vs HTTP2 [16] — HTTP2 может сильно ускорить загрузку страницы за счет мультиплексирования или сжатия заголовков. Помимо этого, новый (относительно) протокол открывает кучу возможностей, например server push.
Domain sharding [17]. Если для запросов к API вам нужно передавать много HTTP заголовков, а для запросов к статике — нет, то лучше разделить их по разным доменам.
CDN (content delivery network) [18] поможет ускорить загрузку для территориально распределенных клиентов.
Resource prioritization (preload, prefetch, preconnect) [19] — это ускорение загрузки страницы за счет правильной стратегии загрузки ресурсов. Браузеры позволяют устанавливать приоритеты для разных типов ресурсов и загружать раньше то, что важно для первой отрисовки.
Static compression: GZIP and Brotli [20]. Brotli — это алгоритм сжатия, который уменьшит вес статики и, соответственно, увеличит скорость загрузки. А вот отличное решение [21] от моего коллеги.
Webp vs Png & Jpg [22]. Webp — отличная альтернатива Png. Помимо меньшего веса изображений, Webp не уступает по качеству. Сейчас этот формат поддерживает примерно 78% браузеров [23]. Но даже если вам нужна 100% поддержка, можно реализовать фоллбэк на Png с помощью тэга picture [24].
Tasks, Microtasks [25]. С помощью правильной приоритизации выполнения кода можно избавиться от «фризов» и ускорить реагирование на пользовательский ввод.
requestIdleCallback [26] — полезная функция, которая позволяет выполнить код в свободное время в конце кадра (фрейма/тика) или когда пользователь неактивен. Поможет избавиться от всех тех же лагов и «фризов».
requestAnimationFrame [27] позволяет правильно запланировать анимацию и максимально увеличить шансы на рендеринг 60 кадров в секунду.
ES2015 vs ES5 [28]. ES2015 предоставляет много функций, более производительных, чем ES5.
DOM manipulation [29]. Манипуляции с DOM — дорогие, выполнять их нужно аккуратно и осмысленно. Например, не вызывать querySelector() в цикле, если это можно сделать одним вызовом.
Render blocking resource [30]. Загрузка некоторых ресурсов может блокировать рендеринг. Чтобы этого избежать, нужно пользоваться атрибутами defer, async, preload.
60 FPS by pointer-events: none [31] — отличный хак, с помощью которого можно достичь 60 FPS при скролле страницы. Работает очень просто: на время прокрутки отключаются все обработчики события мыши.
Passive event listener [32] — способ сделать плавную прокрутку страницы на сенсорных экранах. Коротко говоря, браузер имеет несовершенный флоу обработки слушателей touch events. Если при создании обработчика события установить параметр passive, то браузер будет однозначно понимать, что обработчик не будет отменять прокрутку и рендерить, не дожидаясь его завершения.
Virtual scroll [33] — умный способ не рендерить большие списки, а генерировать их при прокрутке. Позволяет потреблять меньше памяти и облегчить скроллинг списков.
Avoid large Complex Layouts and Layout Thrashing [34]. Layout/reflow — это дорогие операции, которые выполняют много пересчетов параметров рендеринга. Чтобы избегать их частого вызова, нужно правильно строить верстку и манипулировать DOM.
What forces layout / reflow [35] — шпаргалка, в которой можно найти список функций и параметров, работа с которыми вызывает layout/reflow.
Tree shaking [36] — убираем неиспользуемый код из бандла и ускоряем загрузку страницы.
Code splitting [37] — разделив код на чанки, можно оптимизировать первую загрузку и открыть возможность загружать части кода «лениво».
Obfuscation [38] может уменьшить размер бандла и даже немного поможет скрыть ваш код от чужих глаз.
Server side rendering [39] — наверное, самый известный способ сделать так, чтобы SPA рендерилось сразу, при первой загрузке. Это важное требование для некоторых поисковых систем (и не только).
Lazy loading images and video [40] (+native [41]) — нативное решение, призванное улучшить метрики первой отрисовки за счет «ленивой» загрузки изображений и видео.
Lazy loading modules/routes [42] — инструмент, который есть во всех популярных фреймворках и библиотеках. Позволяет «лениво» подгружать куски функциональностей приложения.
Caching files with Service workers [43] позволяет кешировать файлы в браузере и не загружать их каждый раз с сервера. Возможно, единственный способ сделать офлайн-режим в браузерном приложении.
HTTP Caching [44] — с помощью некоторых HTTP-заголовков можно сильно улучшить скорость загрузки страниц и снизить нагрузку на сервер.
Автор: Alexandr Kazachenko
Источник [45]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/347185
Ссылки в тексте:
[1] Time to First Byte: https://developer.mozilla.org/en-US/docs/Glossary/time_to_first_byte
[2] First Contentful Paint: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/First_contentful_paint
[3] First Meaningful Paint: https://developer.mozilla.org/en-US/docs/Glossary/first_meaningful_paint
[4] Time to interactive: https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive
[5] Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools
[6] Firebug/Firefox developer tools: https://getfirebug.com/
[7] Network: https://developers.google.com/web/tools/chrome-devtools/network/reference
[8] Performance: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference
[9] Lighthouse: https://developers.google.com/web/fundamentals/performance/get-started/measuringperf-2
[10] Webpagetest: https://www.webpagetest.org/
[11] mPulse: https://developer.akamai.com/akamai-mpulse-real-user-monitoring-solution
[12] Sematext: https://sematext.com/
[13] Webpack-bundle-analyzer: https://github.com/webpack-contrib/webpack-bundle-analyzer
[14] TCP connection, DNS lookup: https://medium.com/better-programming/understanding-browser-networking-and-how-to-optimize-the-requests-for-http-1-1-and-http-2-f6371f0af650
[15] TTFB (Time to First Byte): https://web.dev/time-to-first-byte/
[16] HTTP1 vs HTTP2: https://medium.com/@factoryhr/http-2-the-difference-between-http-1-1-benefits-and-how-to-use-it-38094fa0e95b
[17] Domain sharding: https://developer.mozilla.org/ru/docs/Web/HTTP/Connection_management_in_HTTP_1.x#%D0%94%D0%BE%D0%BC%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_(Domain_sharding)
[18] CDN (content delivery network): https://imagekit.io/blog/content-delivery-network-improve-website-performance/
[19] Resource prioritization (preload, prefetch, preconnect): https://developers.google.com/web/fundamentals/performance/resource-prioritization
[20] Static compression: GZIP and Brotli: https://medium.com/@suneetbansal/brotli-vs-gzip-compression-surprising-compression-result-8de14e0574a
[21] отличное решение: https://habr.com/ru/company/tinkoff/blog/474632/
[22] Webp vs Png & Jpg: https://web.dev/serve-images-webp/
[23] формат поддерживает примерно 78% браузеров: https://caniuse.com/#search=webp
[24] picture: https://developer.mozilla.org/ru/docs/Web/HTML/Element/picture
[25] Tasks, Microtasks: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide
[26] requestIdleCallback: https://developers.google.com/web/updates/2015/08/using-requestidlecallback
[27] requestAnimationFrame: https://developer.mozilla.org/ru/docs/DOM/window.requestAnimationFrame
[28] ES2015 vs ES5: https://v8.dev/blog/high-performance-es2015
[29] DOM manipulation: https://dev.to/grandemayta/javascript-dom-manipulation-to-improve-performance-459a
[30] Render blocking resource: https://web.dev/render-blocking-resources/
[31] 60 FPS by pointer-events: none: https://habr.com/ru/post/204238/
[32] Passive event listener: https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners?hl=ru
[33] Virtual scroll: https://dev.to/adamklein/build-your-own-virtual-scroll-part-i-11ib
[34] Avoid large Complex Layouts and Layout Thrashing: https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing
[35] What forces layout / reflow: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
[36] Tree shaking: https://medium.com/@netxm/what-is-tree-shaking-de7c6be5cadd
[37] Code splitting: https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting
[38] Obfuscation: https://obfuscator.io/
[39] Server side rendering: https://medium.com/@baphemot/whats-server-side-rendering-and-do-i-need-it-cb42dc059b38
[40] Lazy loading images and video: https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video
[41] +native: https://css-tricks.com/native-lazy-loading/
[42] Lazy loading modules/routes: https://web.dev/route-level-code-splitting-in-angular/
[43] Caching files with Service workers: https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker
[44] HTTP Caching: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
[45] Источник: https://habr.com/ru/post/489230/?utm_source=habrahabr&utm_medium=rss&utm_campaign=489230
Нажмите здесь для печати.