Кто из Вас уже использует прогрессивную загрузку в своих проектах? А как насчет tree-shaking и code-splitting в React и Angular? Успели ли Вы настроить под себя сжатие Brotli или Zopfli, сшивание OCSP и сжатие HPACK? Не стоит ещё забывать о подсказках ресурсов, клиентских подсказках и сдерживании CSS — и это не говоря уже о IPv6, HTTP/2 и сервис воркерах.
Давайте вспомним дни, когда производительность часто уходила на второй план. Дело доходило до неё аж в конце проекта, и в большинстве случаев это сводилось к минификации, конкатенации и оптимизации содержимого и, возможно, к паре дополнительных строк в конфигурационном файле сервера. Оглядываясь на те времена, понимаешь, что ситуация значительно поменялась с тех пор. Производительность касается не только технической стороны вопроса: она действительно важна, и нужно учитывать, как может отразиться на производительности то или иное решение ещё в момент создания дизайна. Производительность нужно постоянно замерять, отслеживать и улучшать, и вечнорастущая сложность веб-технологий всё чаще бросает разработчику вызов, делая невозможным отслеживание метрик, так как они будут значительно отличаться от устройства к устройству, от браузера к браузеру, будут зависеть от сетевого протокола, типа сети и задержки в ней (CDN-ы, ISP, кэши, прокси, фаерволы, балансировщики нагрузки и сами сервера играют большую роль в конечной производительности).
Если бы Вам пришлось сделать обзор на все возможные технологии, с которыми придется встретиться в случае, если поставлена задача улучшить производительность Вашего сайта — от самого начала процесса и до финального релиза — на что бы Вы обратили своё внимание? Ниже приведён (надеюсь, беспристрастный и объективный) чеклист производительности front-end’а на 2017 — обзор всех тем, с которыми Вам возможно придется столкнуться для обеспечения максимально быстрого отклика и плавности работы Вашего вебсайта. (Вы также можете просто загрузить чеклист в PDF (ENG) (0.129 MB) , загрузить чеклист в PDF (RUS) (0.129 MB) или скачать чеклист в формате Apple Pages (ENG) (0.236 MB). Cчастливой оптимизации!)
Текущие микро-оптимизации — это отличный способ, чтобы удерживать Ваш продукт в строю, но гораздо важнее предопределить, какие цели стоят перед Вами, и не забывать о них, ведь они будут влиять на все решения, принимаемые на протяжении всего процесса. Существует множество разнообразных моделей, и приведенные ниже могут варьироваться, но главное ведь — расставить в своём проекте правильные приоритеты.
По результатам психологического исследования оказалось, что если Вы хотите, чтобы пользователь ощущал, что Ваш вебсайт работает быстрее других, нужно быть как минимум на 20% быстрее. Не столь важно время полной загрузки и отображения страницы, как условные метрики, например, а ещё время начала рендера страницы, первой значительной отрисовки (к примеру, время, которое необходимо, чтобы страница отобразила свой основной контент) и время интерактивности (то есть время, необходимое странице, чтобы предоставить пользователю возможность взаимодействия с ней). Измерьте время начала рендера (с помощью WebPagetest) и время отображения первой значимой картинки (с помощью Lighthouse ) на Moto G, на устройстве Samsung среднего уровня производительности и на добротном среднестатистическом устройстве, например Nexus 4, желательно в открытой лаборатории девайсов — на стандартных скоростях 3G, 4G и при подключении к точке доступа Wi-Fi.
Lighthouse, ПО для ревизии производительности от Google.
Обратите внимание на Вашу аналитику, чтобы определить, на чём концентрируются пользователи. Тогда Вы сможете сымитировать 90% пользовательского экспириенса синтетическим тестированием. Соберите информацию, составьте таблицу, сожмите её на 20% и таким образом определитесь со своими целями (например, с бюджетом производительности). Теперь у Вас есть что-то измеримое, на что можно ориентироваться в тестировании. Держа в голове мысль о бюджете производительности, и предпринимая попытки написания хоть малейшего скрипта для уменьшения времени интерактивности, Вы можете быть уверены, что Вы — на верном пути.
Билдер бюджета производительности от Брэда Фроста.
Поделитесь чеклистом с коллегами. Удостоверьтесь, что каждый член Вашей команды ознакомлен с данным чеклистом, чтобы избежать возможного недопонимания в будущем. Каждое принятое решение имеет влияние на производительность, и проект будет только в выигрыше, если не только фронтендеры, но и UX и графические дизайнеры решатся следовать этому плану. Обозначьте решения дизайнера в бюджете производительности и расставьте приоритеты, о которых упоминалось выше.
Модель производительности RAIL ставит перед Вами амбициозные цели: приложите все усилия и предоставьте пользователю отклик в течении 100 миллисекунд после первого входа. Для создания возможности отклика <100 миллисекунд страница должна уступать управление главному потоку не позже, чем через каждые <50 миллисекунд. Для точек повышенной нагрузки — таких, как анимация, лучшим решением будет не нагромождать там, где есть такая возможность, а там, где её нет - обходиться самым минимумом. Более того, каждый кадр анимации должен сменяться менее чем за 16 миллисекунд, тем самым Вы достигнете заветных 60 fps (1 секунда ÷ 60 = 16.6 миллисекунд) — а ещё лучше – уложиться в пределы 10 миллисекунд. Вашему браузеру ведь нужно время, чтобы отрисовать новый кадр на экране, так что постарайтесь, чтобы исполнение Вашего кода завершилось в течение 16.6 миллисекунд. Будьте оптимистом и используйте время простоя с умом. Очевидно, что эта цель относится в большей степени к производительности во время выполнения, а не во время загрузки.
Несмотря на сложность достижения, Вашей абсолютной целью должно быть начало отрисовки страницы уже через 1 секунду и значение индекса скорости менее 1000 (на высокоскоростном подключении). Максимально допустимая длительность отрисовки первого значимого изображения – 1250 миллисекунд. Для мобильных устройств неплохим показателем будет начало отрисовки страницы меньше, чем через 3 секунды для 3G подключения. Если Ваши показатели слегка перевалили за это значение – ничего страшного, но старайтесь понизить эти показатели как можно сильнее.
Не стоит слишком зацикливаться на том, что считается трендовым инструментом в данный момент. Придерживайтесь в выборе собственных интересов в разработке, не важно, будет ли это Grunt, Gulp, Webpack, PostCSS или комбинация нескольких. До тех пор, пока Вам удается получать результат быстро, и Вы не ощущаете проблем в процессе использования инструментов сборки – у Вас должно быть всё хорошо.
Смело делайте ставку на прогрессивное улучшение в качестве ведущего принципа архитектуры вашего front-end’а. Сначала спроектируйте и реализуйте базовые возможности, и только потом дополняйте их сложными фичами для подходящих браузеров, создавая отказоустойчивый интерфейс. В том случае, если Ваш вебсайт работает быстро на медленном устройстве со слабым браузером и посредственным интернетом, то Вы можете быть уверены, что он будет отлично работать на устройстве побыстрее, с современным браузером и хорошим интернет соединением.
Присмотритесь к фреймворку, который позволяет отрисовать картинку на стороне сервера. Не забудьте замерять время загрузки как в режиме отрисовки на сервере, так и на клиенте для мобильных устройств, прежде чем приступать к работе с фреймворком (так как эти изменения в будущем может быть невероятно сложно воплотить). Если Вы уже используете JavaScript фреймворк, убедитесь, что Ваш выбор является оптимальным и справедливым. Каждый из фреймворков по-своему будет влиять на конечную производительность и будет требовать индивидуальной стратегии оптимизации, поэтому Вам нужно отчетливо понимать всю подноготную выбранного фреймворка. В процессе построения веб-приложения обратите внимание на шаблон PRPL и архитектуру оболочки приложения.
PRPL отвечает за выгрузку критично важных ресурсов,
Рендер изначальных маршрутов, пре-кэширование остальных маршрутов и lazy-load остальных маршрутов по запросу.
Оболочкой приложения называют
минимальный HTML, CSS и JavaScript, предоставляющий интерфейс пользователя.
В зависимости от Ваших приоритетов и стратегии организации рабочего процесса, Вам предстоит выбирать между Google AMP и Instant Articles от Facebook. Конечно, Вы можете добиться отличной производительности и без них, но AMP, к примеру, предлагает фреймворк с превосходной производительностью и бесплатным доступом к СDN, а Instant Articles взвинтят показатели производительности на Facebook. Вы, кстати, можете и сами заняться построением прогрессивных веб-приложений.
В зависимости от того, насколько статична информация на вашем вебсайте,
Вы можете попробовать вынести часть контента во
внешний ресурс (static site generator),
выгрузив ее на CDN и запрашивая оттуда статическую версию контента
при необходимости, таким образом Вы спасётесь от запросов к базе данных.
Вы даже можете выбрать для себя статические
хостинг-платформы базирующиеся на CDN, обогащая страницы вашего вебсайта
интерактивностью, в качестве прогрессивного улучшения
(JAMStack).
Обратите внимание, что Вы можете использовать CDNы и для разгрузки (распределения)
динамического контента. Так что не обязательно ограничиваться в использовании CDN только статическим контентом.
Обязательно перепроверьте, выполняет ли выбранная CDN сжатие и преобразование контента, умную выгрузку HTTP/2, имеется ли возможность
сборки статической и динамической части контента для страницы на стороне CDN’а (ближайший по расположению
сервер для пользователя), и другие необходимые задачи.
Было бы мудро для начала ознакомиться, с чем Вам придётся работать. Проведите «инвентаризацию» всех своих ресурсов и контента
(JavaScript, изображения, шрифты, внешние скрипты, “увесистые” модули на странице, такие как карусели, сложная инфографика и мультимедийный контент),
и разделите их на группы.
Составьте таблицу. Определите основные моменты для устаревших
браузеров (т. е. полностью доступный основной контент), затем
улучшенный интерфейс для подходящих браузеров
(т.е. улучшенный функционал, полный интерфейс взаимодействия) и
дополнения (активы, которые не являются абсолютно необходимыми
и могут быть подгружены позже (lazy-load),
такие как веб шрифты, излишние стили, скрипты каруселей, видеоплейеры,
кнопки социальных сетей, крупные изображения).
В качестве примера рекомендуется к рассмотрению статья
"Improving Smashing Magazine’s Performance" , которая описывает этот подход в подробностях.
Что бы развернуть главную часть интерфейса в устаревших браузерах и
добавить продвинутый функционал для современных браузеров — используйте
технику «Сбора вершков». Чётко разделите
процесс на стадии: выгрузите главную часть моментально,
улучшения – по событию DomContentLoaded
и прочие дополнения по событию load
.
Обратите внимание, что данная техника уменьшает зависимость
производительности браузера от устройства, и это в наше
время всё ещё имеет смысл. Например, в развивающихся странах
дешевые смартфоны на Android в большинстве своём используют
Chrome и смогут «собрать вершки» несмотря на их ограниченные память
и возможности процессора. Знайте, что поскольку у нас с
Вами нет альтернативы данной технике, её использование
в последнее время стало более ограниченным.
Некоторым приложениям может понадобиться какое-то время, прежде чем Вы сможет отрендерить страницу. Гораздо лучшим решением будет показывать скелет приложения вместо индикаторов загрузки. Присмотритесь поближе к модулям и техникам по уменьшению скорости изначальной отрисовки страницы (например, tree-shaking и разделение кода), потому что большая часть времени тратится именно на этом этапе на парсинг информации для приложения. Также используйте преждевременный компилятор чтобы выполнить как можно более весомую часть рендера на сервере и, следовательно, выведите используемые данные быстро. В конце концов возьмите на вооружение Optimize.js для ускоренной по средствам обертывания часто используемых функций загрузки (это может быть и не нужно).
Прогрессивная загрузка
подразумевает использование отрисовки страницы на сервере, чтобы получить первую значимую картинку максимально быстро,
а также написание хоть минимального JavaScript, чтобы привести время интерактивности ближе ко времени отрисовки первой значимой картинки.
Рендер на клиенте или на сервере? В обоих случая нашей целью должно быть желание добиться прогрессивной загрузки: Используйте рендер на стороне сервера, чтобы получить первую значимую картинку как можно быстрее, а так же добавьте немного JavaScript’а, чтобы привести время интерактивности ко времени первой значимой картинки. А догрузить (или по запросу или когда позволит время) менее значимые функции страницы мы всегда успеем. К сожалению, как заметил Пол Льюис, в большинстве своём фреймворки не берут во внимание понятие приоритетности, которое можно было бы использовать разработчику, и поэтому прогрессивную загрузку довольно сложно имплементировать с большинством библиотек и фреймворков. Если Вам позволяет время и ресурсы, используйте эту стратегию, чтобы достичь идеальной загрузки.
Обязательно перепроверьте, что expires, cache-control, max-age
и
другие заголовки кэша HTTP правильно выставлены. В общем, ресурсы
должны подлежать кэшированию или на очень короткий срок
(если они могут изменяться) или навсегда (если они неизменны) —
Вы можете просто изменять их версию в URL при необходимости.
По возможности, используйте Cache-control: immutable,
предназначенный для защищённых отпечатком пальца статических
ресурсов, во избежание ре-валидации (на момент написания –
Декабрь 2016 - поддерживается только в Firefox (supported only in Firefox)
по транзакциям https://
). Вы можете использовать
праймер заголовков HTTP кэша Хироку ,
«Лучшие практики по кешированию» Джейка Арчибальда
и
Праймер кэширования HTTP от Ильи Григорика в
качестве руководства.
Когда пользователь запрашивает страницу, браузер извлекает HTML и
строит DOM, потом собирает CSS и строит CSSOM, и только потом генерирует
дерево рендера в соответствии с DOM и CSSOM. Если какой-либо скрипт должен
отработать по умолчанию, браузер не начинает рендер страницы, пока скрипт не
закончит работу, что вызывает задержки рендера. Нам, разработчикам, приходится
настойчиво указывать браузеру, что не стоит ждать окончания выполнения скриптов
для начала рендера страницы. Простейшим способом добиться этого являются HTML
атрибуты defer и async.
На практике, хорошо бы нам отдавать предпочтение defer
перед
async
(как
поблажку для пользователей IE9 и старше, потому что скорее всего иначе Вы сломаете им все скрипты). Также
постарайтесь ограничить влияние сторонних скриптов и библиотек, особенно кнопок
социальных сетей и врезок <iframe>
(карт, например). Вместо этого Вы можете
использовать
статические кнопки социальных сетей
(например, SSBG)
и
статические ссылки на интерактивные карты.
Как можно больше используйте адаптивные изображения с атрибутами srcset,
sizes
и элементом <picture>
. Раз мы уже об этом заговорили, удостоверьтесь, что
Вы используете
WebP формат для работы с изображениями тэга < picture > и резервным изображением
в JPEG (
смотреть пример кода Анрэаса Боуэнса) или используя заголовки Accept.
Sketch нативно поддерживает WebP, и изображения в формате WebP могут
быть экспортированы из Photoshop, используя плагин WebP для Photoshop.
Конечно,
возможны и другие варианты.
Генератор брейкпоинтов для адаптивных изображений автоматизирует создание изображений и разметки.
Вы также могли бы использовать
клиентские подсказки, они как раз сейчас
заручаются поддержкой браузеров.
Не успеваете заняться сложной разметкой для адаптивности Ваших изображений?
Вам в помощь Генератор брейкпоинтов для адаптивных изображений
а также другие сервисы автоматизированной оптимизации изображений,
например Cloudinary. Также, в большинстве случаев использование одних
только srcset
и sizes
принесёт значительную выгоду. Например, ребята из
Smashing Magazine, используют -opt
для имён изображений — например,
brotli-compression-opt.png
; Как только изображение содержит в себе
постфикс opt, каждый член команды знает, что его уже не нужно оптимизировать.
Когда Вы работаете над лэндингом, для которого критичным является молниеносная загрузка некоторых изображений, убедитесь, что Ваши JPEGи прогрессивны и сжаты с помощью mozJPEG (который улучшает скорость начала рендера изображения с помощью манипуляций с уровнями сканирования), Pingo для PNG, Lossy GIF для GIF и SVGOMG для SVG. Размойте ненужные части изображения (применяя к ним размытие по Гауссу), чтобы уменьшить размер, а если даже это не помогает, в конце концов можете попробовать лишать изображение цвета, черно-белое изображение весит гораздо меньше. Для фоновых изображений вполне приемлемым будет экспорт с качеством от 0 до 10%. Всё ещё не довольны результатом? Ну, тогда Вам придется обратиться к технике множественных фоновых изображений.
Велик шанс, что в веб-шрифтах, которые Вы используете в
своём проекте, присутствуют символы, которые Вы не используете.
Вы могли бы попросить поставщика шрифтов сузить набор
символов для ваших нужд или заняться этим самостоятельно,
если Вы используете открытые шрифты (например, включая в алфавит только некоторые символы из латиницы), чтобы уменьшить размеры файла.
Поддержка WOFF2 великолепна, а для
подстраховки Вы можете использовать WOFF и OTF специально
для браузеров с отстающей поддержкой. Также выберите для себя
одну из стратегий Зака Лэзермана – “Полное руководство
по стратегиям загрузки шрифтов,” а также используйте кэш
сервис воркеров для постоянного кэширования шрифтов. Хотите
быстрых результатов? У Pixel Ambacht есть краткое исследование
вопроса (quick tutorial and case study), как привести Ваши
шрифты в порядок.
“Полное руководство по стратегиям загрузки шрифтов,”
Зака Лэзермана предоставляет дюжену опций для улучшения выгрузки шрифтов/
Обязательно используйте Web Font Loader, если Вам приходится использовать внешние сервера для загрузки шрифтов. FOUT лучше чем FOIT; сразу же начните отрисовку текста и загрузите шрифты асинхронно — можете использовать loadCSS для этих целей. Вы также можете обойтись и шрифтами, установленными локально в ОС.
Чтобы быть уверенным на все 100%, что Ваш браузер начнёт
рендер страницы настолько быстро, насколько это возможно,
общепринятой практикой становится собирать
весь необходимый для начала рендера первой видимой части
страницы CSS (известный как «критично-важный» CSS) и добавлять его
инлайново в < head>
вашего документа, таким образом уменьшая
запросы зависимости. Из-за ограничения на передачу пакетов во
время медленной фазы ~ 14 KB это принято считать Вашим бюджетом
критично важных CSS. Если Вы выйдете за рамки бюджета, браузер будет
совершать дополнительные обращения, чтобы выгрузить больше стилей.
CriticalCSS и Critical
позволяют Вам управится с задачей. Вам
скорее всего понадобится проделать это с каждым шаблоном, над
которым Вы работаете. Если возможно, постарайтесь использовать
условно-инлайновый подход
представленный Filament Group.
С появлением HTTP/2, критично важный CSS можно хранить в
отдельном файле CSS и выгружать по запросу с сервера с
помощью сервер пуша, не загрязняя HTML. Загвоздка в том,
что сервер пуш на данный момент не поддерживается и вызывает
некоторые проблемы с кэшированием (слайд 114 презентации Хумана
Бэхешти). Результат может быть негативным, привести
к загрязнению сетевых буферов и предотвращению доставки
истинных пакетов. Сервер пуш гораздо более эффективен
на «тёплом» соединении из-за медленного старта TCP.
Так что Вам может понадобиться создать механизм HTTP/s
сервер пуша, осведомленный о кэше. Помните, что новая
спецификация cache-digest
снизит потребность
в создании таких механизмов вручную.
Tree-shaking — это способ расчистить ваш процесс
сборки, вовлекая только ту часть кода, которая
действительно используется на продакшене.
Вы можете пользоваться Webpack 2, чтобы свести
к минимуму ненужные экспорты кода, и UnCSS
или
Helium, чтобы предотвратить добавление в билд
неиспользуемых стилей. Также Вы могли бы
научиться писать эффективные CSS селекторы
и избегать нагромождения весомых стилей.
Code-splitting — это ещё одна фича Webpack’а,
которая разбивает основание кода на куски и
подгружает по запросу. Как только
Вы определите точки разделения вашего кода,
Webpack сможет позаботиться о зависимостях
и выходных файлах. Он, по сути, позволяет
Вам удержать изначальный трафик в минимальном значении и
запрашивать код при необходимости самим приложением.
Примите к сведению, что Rollup показывает гораздо
лучшие результаты, чем выдает Browserify.
Раз уж мы заговорили от этом, вам может быть
также интересен Rollupify, который превращает
модули ECMAScript 2015 в один большой CommonJS
модуль — потому что маленькие модули могут
требовать на удивление больших затрат
производительности в зависимости от сборщика
и модульной системы, которой Вы пользуетесь.
Изолируйте увесистые элементы с помощью политики сдерживания CSS
— например, что бы ограничить стили браузера для компоновки и
окраса элементов, для навигации вне канваса или для виджетов третьей стороны.
Удостоверьтесь, что нет промедлений при прокрутке страницы и при анимации элементов,
и что пользователь сможет получать стабильные 60 кадров в секунду. Если это не представляется
возможным – как минимум предоставьте диапазон значений FPS в рамках 15-60. Используйте
свойство CSS will-change
, чтобы сообщить браузеру, какие элементы и свойства в будущем
изменятся.
Также, замерьте время производительности рендера (например, в
инструментах разработчика ).
Перед тем как приступить, пройдите бесплатный курс на Udacity – оптимизация рендера браузером.
Используйте скелетные экраны в интерфейсе и lazy load
всех увесистых компонентов, например шрифтов, JavaScript, каруселей,
видео и ifram’ов. Используйте ресурсные подсказки
в целях сохранения времени на dns-prefetch
(который выполняет DNS lookup в фоновом режиме), preconnect
(который просит у браузера разрешение на начало рукопожатий
(DNS, TCP, TLS – так же в фоне), prefetch
(который просит браузер
запрашивать ресурс), prerender
(который указывает браузера как отрендерить
страницу в фоновом режиме) и preload
(который в том числе подготавливает
ресурсы до взаимодействия с ними). Обратите внимание, что на практике в
зависимости от поддержки браузера Вы скорее посмотрите в сторону preconnect
чем dns-prefetch
, и Вы, скорее всего, будете очень осторожны с prefetch
и prerender
— последний
следует использовать только если Вы крайне уверены в том, как пользователь будет себя
вести и каким будет его следующий шаг (хороший пример – воронка продаж).
Вместе с Google, двигающимся в сторону более безопасного веба и окончательного восприятия HTTP страниц Chrome’ом как «небезопасные», Вам придется решиться сделать ставку или на конфигурацию окружения HTTP/2 или остаться на HTTP/1.1. HTTP/2 отлично поддерживается; Он никуда не денется и в большинстве случаев лучше бы Вам принять его сторону. Безусловно, это достаточно трудоемкий процесс, но рано или поздно Вам придется перейти на HTTP/2. Когда Вы с этим покончите, вы получите отличный прирост в производительности с сервис воркерами и сервер пушами.
В итоге, Google собирается помечать все HTTP страницы как небезопасные и менять индикатор безопасности на этих страницах на красный треугольник, такой же, как сейчас у сломанных HTTPS. Отрицательный эффект такая миграция на HTTPS может возыметь в случае, если Ваша база пользователей HTTP/1.1 очень велика и большая часть из них использует устаревшие браузеры и операционные системы. В этом случае Вам придется отправлять разные сборки приложения, которые должны будут адаптироваться под разные процессы взаимодействия. Помните: установка как миграции, так и новой сборки могут быть достаточно сложными и времязатратными. Для последующих частей статьи предположим, что Вы уже переключились на HTTP/2 или уже занимаетесь этим вопросом.
и ещё раз, обработка контента через HTTP/2 требует
больших доработок и сильно отличается от того, как Вы обрабатывали ваши активы раньше.
Вам придется найти баланс между упаковкой всех модулей в один и загрузкой множества
мелких модулей параллельно.
С одной стороны, Вам может показаться хорошей идеей избежать сливания всех активов вместе,
и вместо этого разделить весь Ваш интерфейс на множество маленьких модулей, сжимая и
в процессе сборки, ссылаясь на них с подходом «скаута» и загружая
их в параллели. В отличие от одного файла, в случае неудачной загрузки не придется
выгружать полностью все стили и скрипты заново.
С другой стороны, упаковка всех файлов в один всё ещё имеет право на существование, потому что
есть проблемы с отправкой множества маленьких JavaScript файлов в браузерах.
Во-первых, пострадает сжатие. Компрессия больших файлов изменится в лучшую сторону
благодаря повторному использованию словаря, что не касается отдельных небольших файлов.
Ведется работа над улучшением этого момента, но это ещё далеко от реальности. Во-вторых,
браузеры ещё не оптимизированы
под такой ход работы
с файлами. Например, Chrome сочтет
подобные изменения за межпроцессные коммуникации
между каждым из кластеров, поэтому включая сотни файлов Вы рискуете сильно проиграть в
производительности.
Чтобы достичь лучших результатов используя HTTP/2,
попробуйте <a href="https://jakearchibald.com/2016/link-in-body/" target="_blank">подгружать CSS прогрессивно</a>,
как было предложено Джеком Арчибальдом из Chrome.
</i>
Но Вы всё ещё можете попробовать загружать CSS прогрессивно. Очевидно, что поступая таким образом Вы будете активно ущемлять пользователей HTTP/1.1, так что Вам может понадобится генерация и обработка разных билдов для разных браузеров в процессе вашего деплоймента, и тут всё становится немного сложнее. Вы можете уйти от использования HTTP/2 объединяющим соединением, что позволяет Вам использовать сегментирование доменов, чем значительно отличается от HTTP/2, но на практике достичь этого сложно. Так что же делать? Если Ваш вебсайт работает через HTTP/2, отправка около 10 сегментов является неплохим компромиссом (и это совсем не плохо даже для устаревших браузеров). Просто поэкспериментируйте и вычислите нужный баланс для Вашего вебсайта.
Все браузерные реализации HTTP/2 работаю через TLS, так что скорее всего Вам захочется избежать оповещений безопасности или неработоспособности каких-то элементов на вашей странице. Перепроверьте, что заголовки безопасности правильно настроены, избавьтесь от заранее известных уязвимостей и проверьте Ваш сертификат. Все ещё не перешли на HTTPS? Присмотритесь к HTTPS-Only Стандарту в качестве инструкции. Также удостоверьтесь, что внешние плагины и отслеживающие скрипты загружены через HTTPS, что межсайтовый скриптинг невозможен и что как строгие заголовки транспортной безопасности HTTP, так и заголовки политики безопасности подключений заданы верно.
Разные сервера и CDNы скорее всего будет поддерживать HTTP/2 по-разному. Попробуйте Is TLS Fast Yet? Чтобы уточнить информацию касательно Вашего варианта или в сравнении с другими узнать насколько производителен Ваш сервер и поддержку каких фич стоит ожидать в скором времени.
Ресурс
Is TLS Fast Yet?
Позволяет Вам проанализировать конфигурации серверов и CDN при переходе на
HTTP/2.
В прошлом году Google представили миру Brotli, новый формат данных без потерь, который уже широко поддерживается в Chrome, Firefox и Opera. На практике, Brotli представляется более эффективным чем Gzip и Deflate. Сам процесс сжатия может быть затяжным, в зависимости от настроек и чем дольше длится сжатие, тем выше будет уровень самого сжатия. Кстати говоря, декомпрессия происходит быстро. Не будет сюрпризом, что браузеры будут поддерживать этот алгоритм только если пользователь посещает вебсайт через HTTPS, ведь алгоритм разработан в Google, но на самом деле, на то есть ещё и технические причины. Загвоздка в том, что Brotli не предустановлен на большинстве серверов сегодня, и не так уж просто его настроить без самостоятельной компиляции NGINX или Ubuntu. Однако, Вы можете активировать Brotli даже на тех CDN, которые пока что его не поддерживают(с помощью сервис воркеров). В качестве альтернативы можете рассмотреть алгоритм сжатия Zopfli, который кодирует информацию в форматы Deflate, Gzip и Zlib. Любой ресурс сжатый простым Gzip-ом можно выгодно сжимать с Zopfli’s с улучшенным кодированием Deflate, потому что файлы будут на 3-8% меньше, чем может предоставить лучшее сжатие от Zlib’s. Загвоздка в том, что это займет гораздо больше времени (~в 80 раз дольше). Поэтому использование Zopfli будет отличным решением для ресурсов, которые не очень-то меняются, и файлов, которые были созданы, чтобы однажды быть сжатыми и множество раз скачанными.
Включая сшивание OCSP на своём сервере, Вы сможете значительно ускорить «рукопожатия» протокола TLS. Протокол OCSP (Online Certificate Status Protocol) был создан в качестве альтернативы для протокола CRL (Certificate Revocation List). Оба протокола используются для проверки валидности SSL сертификата. Однако, протокол OCSP не требует, чтобы браузер тратил время, загружая список сертификатов и детальную информацию про них для поиска, таким образом уменьшая время, затраченное на «рукопожатие».
Поскольку запасы адресов IPv4 подходят к концу, большинство мобильных сетей получают поддержку IPv6 просто молниеносно (США достигли порога в 50% поддержки IPv6), будет замечательной идеей обновить поддержку Вашего DNS на IPv6, чтобы в будущем обеспечить себе спокойный сон. Просто убедитесь, что во всей сети предоставляется двойной стэк – IPv4 и IPv6 — это позволит им работать одновременно бок о бок. Помните, IPv6 не обратно-совместимый. Однако, исследования показали, что IPv6 сделал обычные сайты на 10-15% быстрее благодаря технике обнаружения соседа (NDP) и оптимизации маршрута.
В случае, если Вы используете HTTP/2, стоит убедиться, что Ваши сервера используют сжатие HPACK в заголовках HTTP ответов, чтобы уменьшить использование ресурсов. Из-за того, что сервера HTTP/2 относительно молоды, может иметь место неполноценная поддержка спецификаций, с HPACK, например. H2spec это отличный (и очень детализированный) инструмент что бы проверить работоспособность HPACK.
Как ни оптимизируй сетевую передачу данных, она не будет быстрее, чем получение данных из локального кэша, хранящегося на устройстве пользователя. Если Ваш вебсайт использует HTTPS, стоит присмотреться к «Прагматичному гиду по сервис воркерам», чтобы добавлять в кэш сервис воркеров статические материалы и локально хранить оффлайн фолбэки (или целые оффлайн страницы) и открывать их из памяти устройства пользователя, а не отправляться за ними в сеть. Будет полезным также посмотреть «Книгу рецептов для Оффлайна» и бесплатный Udacity курс от Джейка “Offline Web Applications.” Волнуетесь о поддержке браузерами? Не стоит, она на подходе, да и сеть в любом случае останется запасным вариантом.
Если Вы не так давно перешли с HTTP на HTTPS, не забудьте промониторить предупреждения микс-контента, как активного так и пассивного, для этого подойдёт инструмент Report-URI.io. Вы также можете использовать Mixed Content Scan что бы просканировать Ваш вебсайт с активированным HTTPS-на содержание микс-контента.
Выберите для себя инструменты отладки и прокликайте каждую кнопку, каждую ссылку. Убедитесь, что Вы знаете, как проанализировать и улучшить производительность отрисовки страницы, консольный вывод, и как отладить JavaScript или скорректировать CSS стили. Не так давно Умар Ганза (Umar Hansa) подготовил огромную презентацию и речь, в которых упоминаются дюжины неизведанных советов и техник, о которых не стоит забывать, когда дело доходит до отладки и тестирования в Инструментах разработчика (DevTools).
Тестирования в Chrome и Firefox, однозначно, недостаточно. Оцените, как Ваш вебсайт выглядит в прокси-браузере и в устаревших браузерах. К примеру, UC Browser и Opera Mini, занимают огромный сегмент рынка в Азии (до 35%). Исследуйте и замерьте среднюю скорость подключения к сети в странах, на которые ориентирован Ваш продукт, чтобы в будущем не столкнуться с неприятным сюрпризом. Не забудьте провести тестирование с троттлингом и симулировать дисплей повышенной плотности. BrowserStack - это отличный инструмент, но тестирование на физических девайсах не менее важно.
Всегда гораздо выгоднее иметь собственный экземпляр WebPagetest 'а для быстрого и неограниченного тестирования. Установите непрерывный мониторинг за бюджетом производительности с автоматическими извещениями. Установите собственные временные оценки, чтобы измерять, сравнивать и мониторить метрики в зависимости от сферы деятельности. Присмотритесь к использованию SpeedCurve чтобы отслеживать изменения в производительности со временем, и/или New Relic что бы получить выводы, которые WebPagetest не предоставляет. Стоит так же обратить внимание на SpeedTracker, Lighthouse и Calibre.
Список достаточно обширный, и выполнение оптимизации может отнять у Вас порядочно времени. А что, если бы у Вас был лишь 1 час, чтобы добиться значительных улучшений? Какое бы решение приняли Вы? Давайте сузим список до десятки самых легко достижимых целей. Очевидно, Вам придется замерять результаты до начала и после окончания оптимизации, включая время начала рендера и индекс скорости на 3G и проводном подключении.
- Вашей целью является начало отрисовки страницы не позже чем через 1 секунду на проводном подключении и 3 секунды используя 3G, и значение индекса скорости менее 1000. Оптимизируйте время начала отрисовки и время интерактивности.
- Подготовьте критичный CSS для основы интерфейса и включите его в
<head>
вашей страницы. (Ваш бюджет - 14 KB). - Используйте Defer и lazy-load во всех скриптах, где только возможно, как в своих собственных, так и в сторонних — особенно это касается социальных медиа ссылок, видеоплейеров, и увесистого JavaScript.
- Добавьте подсказки ресурсов, чтобы ускорить загрузки с быстрыми
dns-lookup, preconnect, prefetch, preload и prerender
. - Разделите веб-шрифты и загружайте их асинхронно (или просто переключайтесь на системные шрифты, как альтернатива).
- Оптимизируйте изображения, рассмотрите возможность использования WebP для основных страниц (например, лэндингов).
- Удостоверьтесь, что сами заголовки кэша HTTP и их безопасность установлены правильно.
- Активируйте сжатие Brotli или Zopfli на сервере. (В случае если это невозможно, не забывайте про сжатие Gzip.)
- Если HTTP/2 доступен, активируйте сжатие HPACK и начните отслеживать предупреждения смешанного контента. Если Вы работаете над LTS, также активируйте сшивание OCSP.
- Если представляется возможным, кэшируйте содержимое, например шрифты, стили, скрипты и изображения, а вообще, чем больше – тем лучше — в кэше сервис воркеров.
Держа в голове этот чеклист, Вы гарантированно будете подготовлены к разработке любого front-end проекта в 2017 году. Не забудьте скачать PDF файл с чеклистом, подготовленным к печати для Ваших нужд:
Некоторая часть процесса оптимизации может выходить за рамки вашего проекта и/или бюджета, а также быть попросту невыполнимым заданием, работая, скажем, с доисторическим кодом, который Вам достался. Это вполне нормально! Рекомендуется использовать данный чеклист как общие (и, надеюсь, фундаментальные) инструкции, или создать на его основе свой собственный список тем, которые будут применимы для Вашего проекта. Кстати, не забывайте протестировать и замерить результаты Ваших проектов до начала оптимизации, чтобы определить наиболее важные моменты. Удачной всем оптимизации в новом, 2017 году!