Ускоряем загрузку сайта [Client Side]

Предыдущие сообщения
14 марта 2014
#1 Flash_X uid#496 Genius

Последовательность работы браузера

Давайте рассмотрим клиентскую оптимизацию нашего любимого hackersoft.ru :
Что делает браузер после того, как мы сказали ему открыть нужный нам сайт:
  1. Проверка локального кеширования 3ms
  2. DNS loockup 26ms
  3. TCP/IP соединение 145ms
  4. Отправка HTTP запроса 1ms
  5. Ожидание ответа (до получение первого байта) 878ms
  6. Получение ответа 22ms
  7. Обработка ответа и запросы на получение статики (скрипты, стили, картинки) N ms
    • парсинг HTML 252ms
      • Исполнение скриптов 204ms
      • Построение DOM дерева 48ms



До момента загрузки страницы чуть более шести секунд.
До момента отрисовки страницы чуть более двух секунд.

Теперь по порядку:

Проверка локального кеширования

Браузер смотрит на наличие кеша запрашиваемой страницы в стандартном хранилище браузера. Если страница там есть, то браузер только спрашивает у сервера, не изменилось ли что то. Если нет, то запрашивает страницу на загрузку.
Для оптимизации нужно:
  • Добавлять в ответ сервера заголовки кеширования или закешировать страницу с помошью манифеста.
    Заголовок:
    Cache-control:private, must-revalidate
    Манифест:
    <!DOCTYPE html>
    <html manifest="...">

DNS loockup

Что бы сократить время DNS Loockup нужно понимать как работает DNS:
Если объяснять простым языком, то DNS, это хеш таблица в которой ключ это доменное имя, а значение это IP соответствующего ресурса.
Для достижения соединения, двум компьютерам нужно знать IP адреса друг друга.
Когда один компьютер хочет соединиться с другим, то происходит следующее:
  • Происходит проверка локального кеша DNS. Если кеш не пустой и не протух, то происходит соединение, иначе далее...
  • Компьютер спрашивает у известного ему сервера DNS, какой IP у такого то домена. Если DNS знает ответ, то он возвращает IP адресс и происходит соединение.
  • Если нет, Наш DNS сервер опрашивает другие DNS сервера, и если находит ответ, то отдаёт IP и происходит соединение. Иначе сообщается что соответствующего IP не существует.
Для оптимизации нужно:
  • Понимать, где находится целевая аудитория, и использовать ближайшие DNS сервера.
  • Если целевая аудитория находится на очень обширной территории, то использовать CDN.

TCP/IP соединение / передача данных

RTT (Round Trip Time) -- время, которое нужно сети что бы доставить один пакет данных от одного устройства к другому.
MSS (Maxsimum Segment Size) -- максимальная длинна пакета данных при передачи от одного устройства к другому (чаще всего составляет 1460 байт)
Congestion Window -- объём пакета, который машина способна принять за раз. При передаче используется вместо MSS для определения длины пакета (у всех разное, для примера 15 744 байт)

RTT до hackersoft.ru можно узнать просто пинганув его:
user@gnusmas:~$ ping 174.37.250.80 -s 1460
PING 174.37.250.80 (174.37.250.80) 1460(1488) bytes of data.
1468 bytes from 174.37.250.80: icmp_req=1 ttl=54 time=168 ms
1468 bytes from 174.37.250.80: icmp_req=2 ttl=54 time=236 ms
1468 bytes from 174.37.250.80: icmp_req=3 ttl=54 time=167 ms
^C
--- 174.37.250.80 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 167.877/190.840/236.326/32.167 ms
В моём случае это 32 ms.

TCP/IP соединение устанавливается с помощью тройного рукопожатия: спрашивающий компьютер отправляет первый пакет, отвечающий посылает ответный пакет, спрашивающий подтверждает, что всё успешно получено.
Таким образом для установления одного соединения нужно 3 RTT, что равно 32*3 = 96 ms

Каждый файл, который нужно скачать, это +1 соединение (3 RTT).
Каждые 1460 байт файла это +1 RTT.

Для оптимизации нужно:
  • Располагать сервер с сайтом ближе к целевой аудитории.
  • Если целевая аудитория находится на очень обширной территории, то использовать CDN.

Отправка HTTP запроса

Тут я не знаю что оптимизировать. (всё есть в пункте "Проверка локального кеширования" )

Ожидание ответа (до получение первого байта)

После того как мы отправили запрос к серверу, пользователь видит следующее:


(скрин редактированный, ибо ну удалось запечатлеть момент)

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

Для оптимизации нужно:
  • Начать отдавать html сразу после получения запроса, параллельно генерируя содержимое.
  • Располагать минимальную вёрстку в начале body. Т.е. шапку (header), логотип и прочее. Это делается для того, что бы исчьо до окончания обработки запроса пользователь мог увидеть часть сайта.

Получение ответа

В ответ мы получаем html документ.




Для оптимизации нужно:
  • Включить gzip на сервере.
  • Максимально минифицировать html документ (убрав всё форматирование кода + вырезав не нужные комментарии).
Помните, Congestion Window всегда разный, и каждый лишний символ(байт) может создать добавочный RTT, что добавит несколько ms к загрузке страницы

Обработка ответа и запросы на получение статики (скрипты, стили, картинки)

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

Для оптимизации нужно:
  • Перенести все теги script в конец тега body.
  • у тегов script установить атрибуты defer и async




Если взглянуть на то, что тащит фронтпейдж у hackersoft.ru, то можно увидеть что мы скачиваем:
32 картинки
5 стилей
5 скриптов

У браузера есть ограничение на количество одновременных соединений на домен (обычно 6-8 ).

Т.е. если нужно одновременно загрузить 42 файла с одного домена, то браузер начнёт загружать 6 первых файлов, и по мере завершения загрузок, будет подгружать остальные.
Это означает, что у всех последующих файлов будет задержка перед загрузкой.

У домена hackersoft.ru есть кукисы (длинной 322 символа). При каждом запросе за статикой (картинки, скрипты, стили) мы отправляем эти данные на сервер).



Для оптимизации нужно:
  • использовать режим Keep-Alive (для того, что бы загружать все файлы одним подключением).
  • вынести всю статику на отдельный домен, чтобы не посылать кукисы.
  • Использовать несколько поддоменов для параллельной раздачи статики.

Для оптимизации картинок нужно:
  • Склеивать картинки в спрайты, и в css разбивать их на сегменты.
  • Использовать data:image base64 для мелких картинок.
  • Вырезать всю не нужную информацию из файла картинки. Грамотно выбирать цветовой диапазон.
Для оптимизации стилей нужно:
  • Минифицировать стили.
Для оптимизации стилей нужно:
  • Минифицировать скрипты.
  • у тегов script установить атрибут async
З.Ы. Накипело просто.
20:23:08 4
#2 kanaris uid#1 "Мы работаем над этим". :) 21:41:23 0
#3 user uid#4763 22:26:40 0
#4 Flash_X uid#496 Geniusради драматичности момента 22:47:10 1
Следующие сообщения
*Ник: Проверка уникальности... Если вы уже зарегистрированы, авторизуйтесь.
*Сообщение:
  Загрузка...