company_banner

33 способа ускорить ваш фронтенд в 2017 году

https://www.smashingmagazine.com/2016/12/front-end-performance-checklist-2017-pdf-pages/
  • Перевод

enter image description here


Вы уже используете прогрессивную загрузку? А как насчёт технологий Tree Shaking и разбиения кода в React и Angular? Вы настроили сжатие Brotli или Zopfli, OCSP stapling и HPACK-сжатие? А как у вас обстоят дела с оптимизацией ресурсов и клиентской части, со вложенностью CSS? Не говоря уже о IPv6, HTTP/2 и сервис-воркерах.


Были времена, когда производительность зачастую улучшали задним числом. Работу над ней откладывали до самого окончания проекта, и всё сводилось к минификации, конкатенации, оптимизации ресурсов и, если повезёт, нескольким тонким настройкам на стороне сервера. С тех пор ситуация значительно изменилась.


Задача повышения производительности перестала быть сугубо техническим вопросом. Теперь она внедрена в общий рабочий процесс, и те или иные архитектурные решения оцениваются с точки зрения их влияния на скорость работы системы. Производительность нужно постоянно мониторить, измерять и уточнять, но с ростом сложности веба перед разработчиками возникают всё новые проблемы, затрудняющие отслеживание метрик, ведь они сильно зависят от устройств, браузеров, протоколов, типов сетей и задержки (CDN, интернет-провайдеры, кэши, прокси, файрволы, балансировщики нагрузки и серверы — всё это влияет на производительность).


Но если описывать все факторы, о которых следует помнить при улучшении производительности — с начала работы над проектом до запуска сайта, то как будет выглядеть подобный список? Ниже вы найдёте (надеюсь, беспристрастный и объективный) чек-лист по улучшению производительности фронтенда на 2017 год. Это обзор проблем, которые вам потребуется решить для уменьшения времени отклика сайта и его плавной работы.


Чек-лист


Микрооптимизации позволяют держать производительность под контролем, но при этом крайне важно ясно представлять себе конкретные цели: они должны быть измеримы и влиять на все принимаемые в процессе работы решения. Существует несколько разных моделей, и те, что будут обсуждаться дальше, весьма категоричны. Поэтому убедитесь, что вы с самого начала выбрали свои собственные приоритеты.


Подготовка и выбор целей


1. Будьте на 20% быстрее своего самого быстрого конкурента


Согласно одному психологическому исследованию, если вы хотите, чтобы ваши пользователи воспринимали ваш сайт как самый быстрый, вам нужно быть как минимум на 20% быстрее. Время полной загрузки страницы нерелевантно в отличие от таких метрик, как время начала отрисовки, время до первого полезного экрана (то есть время, необходимое для отображения на странице первичного контента) и время до начала взаимодействия (время, через которое страница (и в первую очередь одностраничное приложение) оказывается готова к тому, чтобы пользователь мог с ней взаимодействовать).


Измерьте время до начала отрисовки (с помощью WebPagetest) и до первого полезного экрана (с помощью Lighthouse) на Moto G, каком-нибудь смартфоне Samsung бизнес-класса и заурядном устройстве вроде Nexus 4 (желательно в какой-нибудь открытой лаборатории) на обычных 3G-, 4G- и Wi-Fi-подключениях.



Lighthouse, новый инструмент аудита производительности, разработанный Google


Проанализируйте полученные результаты, чтобы понять, какова ситуация у ваших пользователей. Затем можете для тестирования имитировать 90-й перцентиль. Соберите данные в таблицу, срежьте 20% и поставьте себе конкретные цели (бюджет производительности). Теперь вы можете при тестировании ориентироваться на конкретные показатели. Если вы будете держать бюджет в уме и стараться «придушить» хотя бы самый маленький скрипт ради уменьшения времени до начала взаимодействия, то вы на верном пути.


enter image description here
Performance budget builder


Поделитесь чек-листом с коллегами. Ознакомьте с ним каждого члена команды, чтобы избежать недопонимания. Каждое решение влияет на производительность, и проект очень сильно выиграет от вовлечения фронтенд-разработчиков в процесс принятия решений по концепции, UX и дизайну. Привяжите дизайн решения к бюджету производительности и приоритетам, обозначенным в чек-листе.


2. Время отклика – 100 миллисекунд, 60 кадров в секунду


Модель производительности RAIL задаёт правильные цели: сделайте всё возможное, чтобы пользователи получали отклик раньше, чем через 100 мс после начального ввода данных. Для этого страница должна возвращать управление главному потоку не позднее чем через каждые <50 мс. В высоконагруженных зонах вроде анимации везде, где возможно, лучше ничего больше не делать, либо делать абсолютный минимум.


Кроме того, каждый кадр анимации должен завершаться менее чем за 16 мс, чтобы обеспечить частоту в 60 кадров/с (1 с ÷ 60 = 16,6 мс). Желательно — менее чем за 10 мс. Поскольку браузеру нужно время для отрисовки нового кадра, ваш код должен завершить исполнение раньше 16,6 мс. Будьте оптимистичны и с умом воспользуйтесь временем ожидания. Очевидно, что эти цели относятся к runtime-производительности, а не к производительности загрузки.


3. Первый полезный экран менее чем за 1,25 с, Speed Index ниже 1000


Хотя это может оказаться очень труднодостижимым, ваша главная цель — начало отрисовки менее чем через 1 с и значение Speed Index ниже 1000 (на быстрых подключениях). Время до первого полезного экрана не должно превышать 1250 мс. Для мобильных устройств, подключённых по 3G, считается приемлемым начало отрисовки не позднее чем через 3 с. Даже если будет чуть дольше, не страшно, но старайтесь снизить это значение.


Определите среду


4. Выберите и настройте инструменты для сборки


Не обращайте слишком много внимания на то, что сегодня считается якобы крутым. Придерживайтесь своей среды для сборки, будь то Grunt, Gulp, Webpack, PostCSS или какая-то комбинация инструментов. Пока вы достаточно быстро получаете результаты и не испытываете проблем с поддержанием процесса сборки, вы всё делаете правильно.


5. Прогрессивное улучшение


Пусть прогрессивное улучшение будет основным принципом ваших фронтенд-архитектуры и развёртывания, это беспроигрышный вариант. Сначала проектируйте и создавайте основные схемы взаимодействия, а затем расширяйте их возможностями, поддерживаемыми разными браузерами, создавая отказоустойчивые схемы. Если ваш сайт работает быстро на медленных машинах с паршивенькими экранами, в устаревших браузерах и неоптимальных сетях, то он будет работать ещё быстрее на быстрых машинах с хорошими браузерами и приличной сетью.


6. Angular, React, Ember и компания


Выберите фреймворк, позволяющий выполнять отрисовку на сервере. Обязательно измерьте время загрузки на мобильных устройствах в режимах отрисовки на серверной и клиентской сторонах, прежде чем остановиться на конкретном фреймворке (потом будет очень сложно «менять коней на переправе», и это приведёт к проблемам с производительностью). Если вы решите воспользоваться JS-фреймворком, то обязательно убедитесь, что ваш выбор – продуманный и осознанный. Разные фреймворки по-разному влияют на производительность и требуют разных подходов к оптимизации, так что нужно чётко понимать все преимущества и недостатки выбранного вами инструмента. При создании веб-приложения обратите внимание на PRPL-паттерн и архитектуру оболочки приложения.


enter image description here


PRPL расшифровывается как Pushing critical resource, Rendering initial route, Pre-caching remaining routes and Lazy-loading remaining routes on demand: передача критических ресурсов, отрисовка начального маршрута, предварительное кэширование остальных маршрутов, отложенная загрузка остальных маршрутов по запросу.


enter image description here


Оболочка приложения — это сочетание HTML, CSS и JavaScript, минимально необходимое для работы пользовательского интерфейса


7. AMP или Instant Articles?


В зависимости от приоритетов и стратегии, принятых в вашей организации, вы можете воспользоваться Google AMP или Facebook Instant Articles. Можно и без них добиться хорошей производительности, но AMP предлагает надёжный и быстрый фреймворк с бесплатной сетью доставки контента (CDN), а Instant Articles повышает производительность ваших продуктов в Facebook. Также есть возможность создавать прогрессивные веб-AMP.


8. Выбирайте CDN с умом


В зависимости от того, сколько у вас динамических данных, попробуйте «вынести» часть контента в генератор статических сайтов, передавая его в CDN и обслуживая таким образом статическую версию, избегая запросов к базе данных. Можно даже выбрать платформу статического хостинга на базе CDN, улучшив страницы с помощью интерактивных компонентов-расширений (JAMstack).


Вы обратили внимание, что CDN может обслуживать (и разгружать) ещё и динамический контент? Нет нужды ограничивать её только статическими ресурсами. Удостоверьтесь, что выбранная CDN выполняет сжатие и конвертирование контента, поддерживает умную доставку посредством HTTP/2, технологию ESI, с помощью которой статические и динамические части страниц собираются на стороне CDN (то есть в ближайшей к пользователю серверной части), и решает прочие задачи.


Оптимизация сборки


9. Установите приоритеты


Прежде всего, нужно понимать, с чем вы имеет дело. Проведите инвентаризацию всех ресурсов (JavaScript, изображения, шрифты, сторонние скрипты и «дорогие» модули на странице вроде каруселей, сложной инфографики и мультимедийного контента) и разделите их на группы.


Постройте таблицу. Определите основную функциональность для устаревших браузеров (то есть полную доступность основного контента), расширенную функциональность для современных браузеров (то есть улучшенную, полную функциональность) и дополнительные материалы (ресурсы, в которых нет необходимости и которые могут подгружаться лениво: веб-шрифты, дополнительные стили, скрипты каруселей, видеоплееры, кнопки соцсетей, крупноразмерные изображения). Подробнее об этом можно почитать в статье Improving Smashing Magazine’s Performance.


10. Используйте подход Cutting the Mustard


Он используется для передачи устаревшим браузерам основной, а современным браузерам — расширенной функциональности. Будьте строги при загрузке своих ресурсов: немедленно грузите основную функциональность, расширения — по событиям DOMContentLoaded, а дополнительные материалы — по событиям load.


Обратите внимание, что этот подход определяет возможности устройства по версии браузера, что сегодня делать уже непозволительно. Например, на дешёвых Android-смартфонах в развивающихся странах по большей части работает Chrome, поэтому описанный сценарий будет выполняться, несмотря на небольшой объём оперативки и скромный процессор. Хотя на данный момент альтернатив такому подходу нет, нужно понимать, что в последнее время он всё реже и реже требуется.


11. Рассмотрите вопросы микрооптимизаций и прогрессивной загрузки


В ряде случаев требуется какое-то время на инициализацию приложения, прежде чем отрисовывать страницу. Вместо индикаторов загрузки лучше использовать каркасное отображение. Поищите модули и методики, позволяющие уменьшить время первичной отрисовки (например, Tree-Shaking и разбиение кода), потому что большинство проблем с производительностью относится к первичному парсингу при запуске приложения. Также используйте AOT-компилятор для переноса части клиентской отрисовки на сторону сервера, что ускорит получение достойного результата. Наконец, рассмотрите возможность применения Optimize-js для более быстрой первичной загрузки за счёт обёртывания немедленно вызываемых функций (хотя это может быть уже и необязательно).


enter image description here


Прогрессивная загрузка — это отрисовка страницы на стороне сервера для уменьшения времени до первого полезного экрана (это требует какого-то минимального JavaScript, необходимого для того, чтобы время до начала взаимодействия было близко ко времени до первого полезного экрана)


Что лучше — рендеринг на стороне клиента или сервера? В обоих случаях необходимо настроить прогрессивную загрузку: рендеринг на стороне сервера ускорит появление первого полезного экрана, но это требует какого-то минимального JavaScript, необходимого для того, чтобы время до начала взаимодействия было близко ко времени до первого полезного экрана. Потом уже мы можем подгрузить второстепенные части приложения, по запросу или если позволяет время. К сожалению, во фреймворках обычно отсутствует понятие приоритетов, явно предоставляемых разработчикам, так что с большинством библиотек и фреймворков прогрессивную загрузку реализовать непросто. Если у вас есть время и ресурсы, то можете воспользоваться этой стратегией для существенного повышения производительности.


12. Правильно ли настроены заголовки HTTP-кэша?


Проверьте, чтобы expires, cache-control, max-age и прочие заголовки HTTP-кэша были настроены правильно. В целом, ресурсы должны кэшироваться либо на очень короткий срок (если они могут измениться), либо на неопределённый (если они статичны) — при необходимости можно поменять их версию в URL.


Чтобы избежать ревалидации fingerprinted-ресурсов, по мере возможности используйте предназначенный для них Cache-Control: immutable (по состоянию на декабрь 2016 года поддерживается только в Firefox в транзакциях https://). Можете почитать пособие по заголовкам HTTP-кэша, статью «Лучшие методики кэширования» и ещё одно пособие по HTTP-кэшированию.


13. Ограничьте влияние сторонних библиотек и асинхронно загружайте JavaScript


Когда пользователь запрашивает страницу, браузер берёт HTML и собирает DOM, затем берёт CSS и собирает CSSOM, а затем – генерирует дерево отрисовки, сопоставляя DOM и CSSOM. Если нужно обработать какой-то JavaScript, то браузер не начнёт отрисовывать страницу, пока не завершится обработка. Поэтому разработчики должны чётко «сказать» браузеру, чтобы он не ждал и сразу начинал отрисовывать. Для скриптов это делается с помощью HTML-атрибутов defer и async.


Но на практике лучше вместо async использовать defer (ради пользователей IE до версии 9 включительно, в противном случае у них могут не работать скрипты). Также рекомендуется ограничить влияние сторонних библиотек и скриптов, особенно кнопок социальных сетей и встроенных <iframe>. В качестве альтернативы можно использовать статичные кнопки соцсетей (например, SSBG) и статичные ссылки на интерактивные карты.


14. Правильно ли оптимизированы изображения?


Как можно больше используйте адаптивные изображения с srcset, sizes и элементом <picture>. И заодно можете применять формат WebP для обслуживания WebP-изображений с элементом <picture> и запасным JPEG (пример кода) либо использовать согласование содержания (content negotiation) (с помощью заголовков Accept). Sketch нативно поддерживает WebP, к тому же есть плагин для экспорта WebP-изображений из Photoshop. Доступны и другие варианты.


enter image description here


Генератор Responsive Image Breakpoints Generator автоматизирует создание изображений и разметки


Можно использовать клиентские хинты, которые сегодня начинают поддерживаться браузерами. Не хватает ресурсов для создания сложной разметки для адаптивных изображений? Для автоматизации оптимизации изображений используйте Responsive Image Breakpoints Generator или сервисы наподобие Cloudinary.


Также во многих случаях применение одних лишь srcset и sizes поможет достичь значительных результатов. В Smashing Magazine для имён изображений мы используем окончание -opt. Например, brotli-compression-opt.png; если изображение имеет такое окончание, то все в команде понимают, что картинка была оптимизирована.


15. Переходите на новый уровень оптимизации изображений


Работая над лэндинговой страницей, для которой важна молниеносная загрузка определённого изображения, убедитесь, что используете прогрессивные JPEG’и со сжатием MozJPEG (это уменьшает время до начала отрисовки за счёт манипулирования уровнями сканирования), Pingo для PNG, Lossy GIF для GIF и SVGOMG для SVG. Примените размытие к маловажным частям изображения (например, с помощью фильтра «размывка по Гауссу»), чтобы уменьшить размер файла. Можно даже уменьшить цветовую палитру или сделать приложение чёрно-белым. Для фоновых изображений при экспорте из Photoshop устанавливайте качество от 0 до 10%, этого будет совершенно достаточно.


Всё ещё недостаточно быстро? Ну, можно ещё улучшить производительность с помощью разных методик, применяемых к фоновым картинкам (1, 2, 3, 4).


16. Оптимизированы ли веб-шрифты?


Наверняка используемые вами веб-шрифты используют глифы и прочие дополнительные символы, которые не будут использоваться. Ради уменьшения размеров файлов можете обратиться к поставщику с просьбой предоставить уменьшенный набор символов или вырезать всё лишнее самостоятельно, если вы используете opensource-шрифты (например, оставив лишь латинский алфавит и несколько акцентирующих глифов). Классная вещь — поддержка WOFF2, а для браузеров, не поддерживающих его, можно применять WOFF и OTF. Также выберите одну из стратегий, описанных в статье Comprehensive Guide to Font Loading Strategies, и используйте кэш сервис-воркера для надёжного кэширования веб-шрифтов.


Нужно быстрое решение? Изучите этот материал, чтобы грузить шрифты в определённом порядке.


enter image description here


В статье Comprehensive Guide to Font Loading Strategies описаны десятки способов улучшения доставки веб-шрифтов


Если вы не можете передавать шрифты со своего сервера и полагаетесь на сторонние хосты, то воспользуйтесь Web Font Loader. Лучше использовать FOUT, чем FOIT. Сразу же начните отрисовывать текст в запасной версии шрифта и подгружайте шрифты асинхронно. Для этого можно применять loadCSS. Возможно, вам вообще удастся обойтись установленными в операционной системе шрифтами.


17. Быстро передавайте критический CSS


Чтобы браузер как можно скорее начинал отрисовывать страницу, стандартной практикой является сбор всего CSS, необходимого для отрисовки первой видимой части страницы («критический CSS», или «CSS без прокрутки экрана» (above-the-fold CSS)) с последующим встраиванием в раздел <head> страницы. Это снижает количество обращений к серверу. Из-за ограниченного размера пакетов, которыми стороны обмениваются в ходе медленной начальной фазы, ваш бюджет критического CSS составляет около 14 Кб. Если вы его превысите, браузеру понадобится дополнительный roundtrip для получения стилей. Удержаться в рамках бюджета вам помогут CriticalCSS и Critical. Возможно, их придётся применять с каждым шаблоном. По мере возможности используйте метод условного встраивания, практикуемый Filament Group.


В случае с HTTP/2 критический CSS можно хранить в отдельном файле и доставлять по инициативе сервера (server push) без раздувания HTML. Суть в том, что такой тип доставки не имеет обязательной поддержки и имеет некоторые проблемы с кэшированием (см. слайд 114 в презентации). Так что эффект может оказаться даже негативным: сетевые буферы увеличатся в размерах, что предотвратит доставку в документ оригиналов фреймов. Из-за медленного старта TCP доставка по инициативе сервера гораздо эффективнее на горячих подключениях. Возможно, вам понадобится создать механизм такой доставки посредством HTTP/2, зависящий от кэша. Но помните, что новая спецификация кэширования отменит необходимость вручную создавать подобные «зависящие от кэша» серверы.


18. Используйте Tree Shaking и разбиение кода для снижения полезной нагрузки


Tree Shaking — это способ очистки вашего процесса сборки за счёт включения только того кода, который используется в рабочем проекте. Для исключения излишек при экспорте можете воспользоваться Webpack 2, а для удаления неиспользуемых стилей из CSS — UnCSS или Helium. Возможно, вам будет полезно почитать о том, как писать эффективные CSS-селекторы, а также как избегать раздувания и повышения стоимости стилей.


Разбиение кода — другая функция Webpack. Кодовая база делится на «чанки», которые грузятся по запросу. После того, как вы укажете точки разбиения в коде, Webpack позаботится о зависимостях и генерируемых файлах. Разбиение кода позволяет уменьшить объём данных при начальной загрузке, подгружая следующие порции кода по мере необходимости.


Обратите внимание, что Rollup демонстрирует гораздо лучшие результаты по сравнению с экспортом Browserify. В этом случае вы, вероятно, захотите «пощупать» Rollupify, преобразующий модули ECMAScript 2015 в один большой модуль CommonJS — ведь маленькие модули могут на удивление сильно снижать производительность в зависимости от выбранного упаковщика (Bundler) и модульной системы.


19. Улучшаем производительность отрисовки


С помощью ограничения CSS мы можем изолировать дорогие компоненты. Например, для ограничения области видимости браузерных стилей, макета, отрисовки для скрытой навигации (paint work for off-canvas navigation) или сторонних виджетов. Убедитесь в отсутствии лагов при прокрутке страницы или при работе анимации элементов. Также проверьте, чтобы частота кадров постоянно была не менее 60 кадров/с. Если этого добиться не получается, то хотя бы удерживайте частоту в пределах от 15 до 60. Чтобы сообщать браузеру, какие элементы и свойства изменятся, используйте will-change из CSS.


Также измеряйте производительность отрисовки в ходе исполнения (например, в DevTools). Для начала ознакомьтесь с бесплатным курсом на Udacity по оптимизации отрисовки в браузере. Также можете почитать статью про анимацию с использованием GPU.


20. Прогрев соединения для ускорения доставки


Используйте каркасное отображение (skeleton screens) и ленивую загрузку всех дорогих компонентов, таких как шрифты, JavaScript, карусели, видео и iframe. Используйте хинты для ресурсов для экономии времени на:


  • dns-prefetch (ищет DNS в
    фоновом режиме),
  • preconnect (просит браузер в фоновом режиме начать хендшейк для установки соединения (DNS, TCP, TLS)),
  • prefetch (просит браузер запросить ресурсы),
  • prerender (просит браузер отрисовать определённые страницы в фоновом режиме),
  • preload (помимо прочего, заранее выбирает ресурсы без их исполнения).

Обратите внимание: на практике в зависимости от поддержки браузера вы предпочтёте preconnect, а не dns-prefetch и с осторожностью будете использовать prefetch и prerender. Последний стоит использовать только в том случае, если вы абсолютно уверены в том, куда отправится пользователь (например, пойдёт дальше по воронке продаж).


HTTP/2


21. Подготовка к HTTP/2


По мере того, как Google идёт к созданию более безопасного веба, и Chrome в конце концов начинает обращаться со всеми HTTP-страницами как с «небезопасными», вам придётся решать, останетесь ли вы на HTTP/1.1 или настроите HTTP/2-среду. HTTP/2 уже очень хорошо поддерживается. Он никуда не денется, и в большинстве случаев лучше придерживаться этого протокола. Вложения существенные, но рано или поздно это придётся сделать. Кроме того, вы можете получить сильный прирост производительности благодаря сервис-воркерам и отправке данных по инициативе сервера (по крайне мере, в долгосрочной перспективе).


Обратная сторона медали: вам придётся мигрировать на HTTPS и в зависимости от того, насколько велика ваша пользовательская база на HTTP/1.1 (пользователи устаревших ОС или браузеров), придётся рассылать разные билды, для чего потребуется создать новый процесс сборки. Имейте в виду: настройка миграции и нового процесса сборки может быть трудной и длительной задачей. Далее по тексту будем исходить из предположения, что вы либо переходите, либо уже перешли на HTTP/2.


22. Правильное развёртывание HTTP/2


Ещё раз: раздача ресурсов через HTTP/2 потребует глубокого пересмотра привычных процессов. Вам придётся найти баланс между упаковкой модулей и параллельной загрузкой многочисленных маленьких модулей.


С одной стороны, вы можете захотеть избежать объединения ресурсов, разбив интерфейс на многочисленные мелкие модули, сжимая их в ходе сборки, ссылаясь на них в рамках scout-методики и параллельно загружая. Изменение одного файла не потребует перезагрузки всей таблицы стилей или JavaScript.


С другой стороны, упаковка имеет смысл, поскольку отправка браузеру многочисленных маленьких JS-файлов сопряжена с определёнными проблемами. Во-первых, ухудшится сжатие. При повторном использовании словаря мы получаем выгоду от сжатия большого пакета, но не отдельных маленьких. Во-вторых, браузеры ещё не оптимизированы для подобных рабочих процессов. Например, для нескольких ресурсов Chrome запускает последовательное выполнение межпроцессных взаимодействий (IPC), так что если у нас будет нескольких сотен ресурсов, то мы получим большие затраты во время исполнения в браузере.


enter image description here


Для достижения наилучших результатов с помощью HTTP/2 воспользуйтесь прогрессивной загрузкой CSS


Также вы можете попытаться прогрессивно грузить CSS. Очевидно, что в таком случае пользователи HTTP/1.1 окажутся в проигрыше, поэтому частью процесса развёртывания может стать генерирование и передача разных сборок разным браузерам. Это несколько усложнит процесс. Ещё вам может помочь объединение (coalescing) HTTP/2-соединений, позволяющее использовать шардинг домена без потери преимуществ HTTP/2, но на практике это труднодостижимо.


Как быть? Если вы используете HTTP/2, то разумным компромиссом может стать отправка примерно десяти пакетов (это не слишком плохо для устаревших браузеров). Поэкспериментируйте и подберите наилучший для вашего сайта вариант.


23. Убедитесь в надёжности системы безопасности вашего сервера


Все браузерные реализации HTTP/2 работают через TLS, так что вы наверняка захотите избежать предупреждений системы безопасности или дисфункции некоторых элементов на странице. Убедитесь в правильности настройки заголовков безопасности, закройте известные уязвимости и проверьте свой сертификат.


Вы ещё не мигрировали на HTTPS? Тщательно изучите стандарт HTTPS-Only. Убедитесь, что все внешние плагины и отслеживающие скрипты грузятся через HTTPS, что атака через межсайтовый скриптинг невозможна, и что правильно настроены заголовки HTTP Strict Transport Security и Content Security Policy.


24. Ваши серверы и CDN поддерживают HTTP/2?


Разные серверы и CDN могут по-разному поддерживать HTTP/2. Для проверки воспользуйтесь инструментом Is TLS Fast Yet? либо проверьте выполнение вашими серверами и поддержку ими возможностей.


enter image description here


Is TLS Fast Yet? позволяет узнать возможности ваших серверов и CDN при переходе на HTTP/2


25. Используется ли сжатие Brotli или Zopfli?


В прошлом году Google представил Brotli, новый opensource-формат данных без потерь, который сегодня широко поддерживается в Chrome, Firefox и Opera. На практике Brotli получается эффективнее Gzip и Deflate. В зависимости от настроек этот формат может сжиматься медленнее, но зато степень сжатия получается выше.


Однако распаковка выполняется быстро. Поскольку формат разработан Google, неудивительно, что браузеры принимают его только при посещении сайтов через HTTPS. К слову, для этого есть технические причины. Сегодня Brotli не предустанавливается на большинстве серверов, и его не так просто настроить. (прим. переводчика: Достаточно собрать соответствующий модуль от google или cloudflare и динамически подключить его, для чего nginx понадобится только лишь перечитать конфиг) Однако вы можете включить Brotli даже в тех CDN, которые его пока не поддерживают (с помощью сервис-воркера).


В качестве альтернативы можно использовать алгоритм сжатия Zopfli, кодирующий данные в форматы Deflate, GZIP и ZLIB. При сжимании любого ресурса обычным GZIP вы выиграете от применения Deflate-кодирования, улучшенного с помощью Zopfli, потому что файлы станут на 3–8% меньше, чем при максимальном ZLIB-сжатии. Проблема в том, что сжимание будет идти примерно в 80 раз дольше. Поэтому рекомендуется применять Zopfli для тех ресурсов, которые не сильно меняются, а также для файлов, которые сжимаются один раз и многократно скачиваются.


26. Включён ли OCSP stapling?


Включив на своих серверах OCSP stapling, вы можете ускорить TLS-хендшейки. Протокол Online Certificate Status Protocol (OCSP) был создан в качестве альтернативы протоколу Certificate Revocation List (CRL). Они оба используются для проверки аннулирования SSL-сертификата. Однако OCSP не требует от браузера скачивать список сертификатов и потом искать в нём нужную информацию, что экономит время, затрачиваемое на хендшейки.


27. Вы уже внедрили IPv6?


В связи с исчерпанием IPv4 и быстрым внедрением IPv6 в основных мобильных сетях (в США достигнут порог 50-процентного внедрения (по ссылке – 29.66%, – прим. переводчика) ) имеет смысл обновить ваш DNS до IPv6. Убедитесь, что в рамках сети обеспечивается поддержка двойного стека — это позволяет одновременно использовать IPv6 и IPv4. Имейте в виду, что IPv6 не имеет обратной совместимости. Исследования показывают, что этот протокол может ускорять работу сайтов на 15% за счёт «обнаружения соседей» (NDP) и оптимизации маршрутов.


28. Вы используете сжатие HPACK?


Если вы используете HTTP/2, то проверьте, чтобы ваши серверы применяли HPACK-сжатие для заголовков HTTP-откликов. Это уменьшает ненужные накладные расходы. Из-за своей новизны HTTP/2-серверы могут поддерживать спецификации не полностью, в том числе и HPACK. Можете проверить это с помощью прекрасного инструмента H2spec. Работа HPACK.


enter image description here
H2spec


29. Используются ли сервис-воркеры для кэширования и как сетевой fallback (network fallbacks)?


Никакие оптимизации производительности в рамках сети не могут сравниться с кэшем, хранящимся на пользовательском компьютере. Если ваш сайт работает через HTTPS, то изучите руководство Pragmatist’s Guide to Service Workers, чтобы кэшировать статические ресурсы в кэше сервис-воркера, а также сохранять резервный оффлайн-контент (или даже страницы целиком) с последующим извлечением с пользовательской машины вместо передачи по сети. Почитайте также Offline Cookbook и изучите бесплатный курс на Udacity Offline Web Applications. В браузерах появляется поддержка, а сеть в любом случае выступает в качестве резервного решения.


Тестирование и мониторинг


30. Отслеживайте предупреждения о смешанном контенте (mixed-content warnings)


Если вы недавно мигрировали с HTTP на HTTPS, то обязательно отслеживайте активные и пассивные предупреждения о смешанном контенте. Это можно делать с помощью report-uri.io. Также можно сканировать HTTPS-сайт на наличие смешанного контента с помощью Mixed Content Scan.


31. Оптимизирован ли ваш процесс разработки?


Выберите инструмент для отладки и кликните по каждой кнопке. Убедитесь, что вы знаете, как анализировать производительность отрисовки и выводимые в консоль данные, как отлаживать JavaScript и редактировать CSS-стили. В этом выступлении рассматриваются десятки неясностей и рисков в ходе отладки и тестирования с помощью инструментов разработчика.


32. Вы провели тестирование в устаревших и прокси-браузерах?


Недостаточно просто протестировать в Chrome и Firefox. Проверьте, как ваш сайт работает в устаревших и прокси-браузерах. К примеру, UC Browser и Opera Mini занимают приличную долю рынка в Азии (до 35%). Измерьте среднюю скорость интернета в ваших целевых странах, чтобы избежать неприятных сюрпризов. Протестируйте в условиях регулирования полосы пропускания, эмулируйте устройства с высоким значением DPI. BrowserStack — вещь фантастическая, но обязательно проводите тесты и на реальных устройствах.


33. Настроен ли у вас непрерывный мониторинг?


Наличие собственного экземпляра WebPagetest полезно для быстрого тестирования без ограничений. Настройте непрерывный мониторинг бюджета производительности с автоматической рассылкой предупреждений. Также настройте собственные пользовательские временные метки (user timing marks) для измерения и мониторинга специфических бизнес-метрик. Отслеживать изменение производительности можно с помощью SpeedCurve и/ или New Relic. Это поможет понять ограничения WebPagetest. Также обратите внимание на SpeedTracker, Lighthouse и Calibre.


Быстрые результаты


У нас получился достаточно объёмный список, и оптимизация займёт какое-то время. А если у вас есть всего один час, чтобы значительно улучшить производительность? Давайте сведём наш список к десяти самым быстрорешаемым задачам. Конечно, перед началом оптимизации и по её окончании необходимо будет провести измерения, включая время начала отрисовки и значение Speed Index при 3G- и кабельном соединении.


  1. Ваша цель — начать отрисовку менее чем через одну секунду для кабельного и менее чем через три секунды – для 3G-соединения. Значение SpeedI ndex — менее 1000. Оптимизируйте время начала отрисовки и время до начала взаимодействия.


  2. Подготовьте критический CSS для ваших шаблонов и включите его в <head> (ваш бюджет — 14 Кб).


  3. Откладывайте и лениво загружайте как можно больше скриптов (как своих, так и сторонних), особенно кнопки социальных сетей, видеоплееры и дорогой JavaScript.


  4. Воспользуйтесь хинтами для ресурсов ради ускорения доставки с помощью dns-lookup, preconnect, prefetch, preload и prerender.


  5. Используйте уменьшенные наборы символов в веб-шрифтах и грузите их асинхронно (или вообще переключитесь на системные шрифты).


  6. Оптимизируйте изображения и постарайтесь использовать WebP на наиболее важных страницах (например, лэндинговых).


  7. Проверьте правильность настройки заголовков HTTP-кэша и заголовков безопасности.
  8. Включите на сервере сжатие Brotli или Zopfli. Если это невозможно, то не забудьте включить GZIP-сжатие.


  9. Если доступен HTTP/2, то включите HPACK-сжатие и начните отслеживать предупреждения о смешанном контенте. Если вы работаете через TLS, то включите OCSP stapling.


  10. По мере возможности кэшируйте такие ресурсы, как шрифты, стили, JavaScript и изображения (чем больше, тем лучше!) в кэше сервис-воркера.

Скачайте чек-лист (PDF, Apple Pages)


Держа в голове этот чеклист, вы будете готовы к работе над любыми проектами по улучшению производительности фронтенда.



Если вам нужны альтернативные решения, обратитесь к чек-листам Дэна Раблика и Джона Яблонски.


Поехали!


Некоторые оптимизации могут не входить в вашу зону ответственности или бюджет либо могут быть просто излишними, если вам приходится работать с legacy-кодом. Ничего страшного! Этот чек-лист можно взять за основу для создания своего собственного списка, учитывающего особенности вашей работы. Но самое важное — тестируйте и измеряйте метрики своих проектов, чтобы выявлять проблемы до выполнения оптимизаций.

Badoo 345,92
Big Dating
Поделиться публикацией

Вакансии компании Badoo

Комментарии 39
  • +8
    34. Не делайте все это сразу после создания репозитария проекта.
  • +2

    Эх, если бы все было так просто :[

    • 0
      +1, все действительно ни разу не просто. Более того, не стоит воспринимать статью как набор ачивок, это может только навредить.
      • 0
        Не рекламы ради, но блин, как приятно для глаза работает сайт автора… Статья в закладку!
    • +1
      (в США достигнут порог 50-процентного внедрения)

      По ссылке 26.66%

      • 0
        29.6 да, вы правы, щас добавлю примечание, спасибо
      • 0
        Отдельное спасибо за Ember в одном списке с React и Angular в пункте 6!
        • +4
          Никак не могу понять, как люди справляются с рекомендацией насчет стилей для первой видимой части страницы, «CSS без прокрутки экрана».

          Лично у меня не было ни одного проекта, где можно было бы отдельно выделить стили, которые позволили бы нормально отрисовать первую видимую часть страницы.

          Я могу выделить стили, которые нормально построют каркас страницы, могу выделить стили для раскраски, для заполнения бэкграундом, для оформления текста, для установки шрифтов, для анимации…

          И да, я это могу все подгружать не сразу, но вот выделить стили, которые позволят нормально показать верхнюю часть, а потом уже стили, которые покажут нормально все остальное, я никогда не видел в природе.

          Уверен, что какой-то синтетический пример придумать можно, но в жизни мне такие не встречались. А вам?

          • 0
            Это обычно фантастика, работает только в том случае, если верхняя часть страницы везде одинаковая и на ней нет особого контента, слайдер или просто текст, тогда просто базовые стили грузишь, а потом стили компонентов.
            • –2
              Посмотрите инструменты вроде criticalcss. В чем проблема вычислить critical-часть для каждой страницы, а потом подгрузить остальной?
              • +5
                Тем, что обычно эта critical-часть — это 90% css и лучше заняться более важными проблемами, такими как загрузка css под разные разрешения, объединение классов итд.
                • 0
                  Просто интересно, сколько 100% css у вас весит?
                  • 0
                    Зависит от проекта и от того, кто его делал, на моей первой работе, бывали такие ребята, которые на 1 сайт тащили по 3 разных слайдера чисто из-за отличий во внешнем виде или из-за того, что в одном можно делать пагинацию картинками, в другом нет, или подключали бутстрап ради модалок, там обычно до 1мб и это длали не новички, а люди со «стажем». У меня обычно до 100кб весь css пропущенный через cssnano, это с base64 иконками и стилями от сторонних библиотек. Конечно если проект большой, там уже больше и там есть смысл разделять.
            • +1
              Если все разбито на компоненты, сами подключающие свои стили, то при сборке c webpack можно выделить нужные компоненты для «первой видимой части страницы» в отдельный бандл и сперва загрузить только его, либо вообще заинлайнить html/css выхлоп, если доступен server-side rendering.
            • 0
              Вам наверное будет вот это интересно почитать про критический css. Есть инструменты которые позволяют его вычислить. Вообще если ваша страница с заинлайненным css весит меньше 14К то оно вообще и не требуется.
            • +1

              Очень раздражает, когда в погоне за скоростью отрисовки, выводят текст, но без форматирования страницы. Начинаешь читать, а тут погружается баннер/картинка, и тебя перекидывается в произвольное место текста (на страницу вверх или вниз). И начинаеш искать, а где я читал?

              • +4
                Еще хуже, когда загрузилось меню, я по нему кликаю, но за миллисекунду до этого грузится баннер, сдвигает меню вниз и мой клик приходится угадайте куда? И это не какой-то там MFA-сайт, это один из самых крупных отечественных банков.

                P.S. Дорогие TM, уже несколько версий в андроид-приложении сидит этот баг — оцениваешь или отвечаешь на комментарий, а плюсик или ответ улетают соседнему комменту сверху!
              • 0
                Особая благодарность автору за instantarticles. Про AMP я знал, а это…
                В общем я увлекаюсь последнее время подобными технологиями. Считаю, что это типо mobile 2.0 (то что раньше делали m.my.domain).

                По поводу асинхронной загрузки. Я тоже пытался сделать Google Page Speed 99%, но у меня это пришло к тому, что у меня страница просто лагала, когда я все асинхронно загружал.

                Как сделать так, что бы некие минимальные стили bootstrap-а грузились вместе со страницей а все остальное варьево позже? Это нужно для того, что бы страница от асунка не лагала. Расковыривать бутстрап я не решился, а готовых решений не нашел
                • 0

                  14кб — это «бюджет» вообще всей первой загрузки по TCP, а вовсе не только CSS.

                  • –1
                    Если речь идет не о HTTP 2.0, то все равно за каждым файлом открывается отдельное соединение. Поэтому 14кб на файл.
                    • 0

                      Там разговор про 14кб идёт именно в контексте критического СSS («включите в <head>» звучит немного неоднозначно, но когда говорят про critical rendering path, то имеют ввиду именно инлайн), так что тут 14кб на всё про всё.
                      Если бы мы отправляли критический CSS отдельным файлом и без HTTP/2, то тогда так бы и было.
                      Но я не встречал, чтобы кто-дь предлагал такой вариант. Если уж мы делаем критический CSS, то выводим его инлайн. Иначе это лишний round-trip, который довольно критичен.

                  • +2
                    Популизм.
                    • 0
                      простите.
                    • 0
                      del
                      • +3

                        Если не использовать все эти новомодные JS фреймворки то скорость и так выше некуда.
                        Мне кажется мы сами себе придумали проблему, а теперь героически её решаем.

                        • 0
                          Слышали ли вы про layout trashing и как с ним бороться? Через request animation frame. Ок, но тогда нужно как-то узнать в raf нужно ли действительно перерисовываться или лезть в DOM за новыми значениями? Следовательно, вам нужно отделение сухих данных для ui и какой-то механизм проверки их на изменения. Так вот, когда вы напишете свою реализацию глубоких проверок и вычленения нужных DOM-нод для последующего обновления, вы поймете, что свелосипедили React.

                          Так что нет, скорость ни разу не «выше не куда», а эти «новомодные JS-фреймворки» решают существующие, а не надуманные, как некоторым хотелось бы верить, проблемы.
                          • +1

                            Вы не поняли моего мессаджа. React и собраться сделаны для реализации веб приложений и в этом случае наверное от их аналогов никуда не деться, но сейчас на них начинают клепать сайты которые великолепно бы легли на шаблоны сервера и работали бы мега быстро даже с полным обновлением страницы.


                            ЗЫ а для решения "layout trashing" надо больше css юзать, а не через JS всё проставлять.

                            • 0
                              А, вы про это, ну тут да, согласен. Имея молоток, все кажется гвоздями.

                              Далеко не всегда хватает css. Для сайтов достаточно, для какого-то интерактива уже нет.
                        • 0
                          Поскольку формат разработан Google, неудивительно, что браузеры принимают его только при посещении сайтов через HTTPS.


                          Does not compute
                          • +2
                            Сегодня Brotli не предустанавливается на большинстве серверов, и его не так просто настроить без перекомпилированных NGINX или Ubuntu.


                            ????

                            Отсутствие смысла, вероятно, вызвано незнанием переводчиком предметной области, потому внесу ясность: для использования бротли нет необходимости перекомпилировать веб-сервер и уж тем более Убунту (особенно для тех, кто использует другую ОС). Достаточно собрать соответствующий модуль от google или cloudflare и динамически подключить его, для чего nginx понадобится только лишь перечитать конфиг и всё.

                            Автору топика в любом случае спасибо за труд, материал полезный и актуальный для широкой аудитории.
                            • 0
                              Спасибо, за замечание — сейчас поправлю. опыта с brotli действительно не было.
                            • 0
                              Спасибо за перевод.
                              Какие-то моменты знал и использовал, какие-то не знал и лично я использовать вряд ли буду (всё-таки много специфичного для фронт-энд), но кое-что почерпнул нового для себя как бэк-эндщика.
                              • 0
                                Рад что кому-то было полезно
                              • 0
                                Интересно, сколько стартапов похоронит эта статья?
                                Спасибо, много действительно полезных вещей!
                                • 0
                                  Есть мнение что стартапы хоронят люди а не статьи

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое