Хитрости производительности веб-приложений
В последние время мы часто обсуждали производительность, и сейчас, пришло время пересмотреть эту тему, приняв во внимание новые аспекты.
Приёмы, упоминаемые в этой статье, не относятся исключительно к PHP, но вы можете быть уверены, что при правильном использовании они выведут ваше приложение на совершенно новый уровень. Заметьте, что мы не будем рассматривать обычные приёмы.
То, что уменьшение количества запросов к файлам CSS, JavaScript и изображений ускоряет работу веб-сайта, а также прочие подобные советы общеизвестны. Вместо этого мы обратим внимание на менее известные и нечасто используемые приёмы.
HTML
1. Удалите несущественные элементы
Чем меньше элементов, тем лучше. Удалите лишний код HTML.
Сравните:
<div>
<div>
<p>Какой-то <span>текст</span>.</p>
</div>
</div>
и
<div>
<p>Какой-то <span>текст</span>.</p>
</div>
Это, конечно не может быть применено во всех без исключения случаях, но общее правило – структурируйте ваш код HTML таким образом, чтобы удалить как можно больше элементов DOM.
Вы также можете уменьшить размер HTML документа, опуская некоторые необязательные тэги. Да, это может показаться уловкой, противоречащей стандартам, поэтому это лучше делать только при публикации кода в сети – таким образом, вы не будете вводить в заблуждение других разработчиков, работающих с тем же кодом.
2. Предвыборка
Предвыборкой называется приём, при котором вы заранее сообщаете браузеру, что вам потребуется тот или иной ресурс. Этим ресурсом может быть IP-адрес домена (предвыборка DNS), статического файла, такого как изображение или файл CSS, либо даже целой страницы.
Когда вы ожидаете, что пользователь перейдёт на другой домен после посещения вашего сайта, или, например, вы храните ваши статические файлы в субдомене, например, images.example.com, предвыборка DNS поможет вам сохранить несколько миллисекунд, которые потребуются DNS серверу, чтобы разрешить доменное имя images.example.com в IP-адрес.
Выигрыш получается небольшой, но при многократном применении, он поможет вам существенно сократить время загрузки запросов, которые делает браузер пользователя.
Предвыборка DNS осуществляется с помощью тэга <link> в заголовке <head>, например:
<link href="//images.example.com" rel="dns-prefetch" />
и поддерживается большинством браузеров.
Если у вас есть какие-либо субдомены, и вы ожидаете, что пользователь будет загружать с них какие-либо файлы после посещения текущей страницы, нет причин отказываться от использования предвыборки DNS.
Когда вы предполагаете, что некоторые ресурсы потребуются при следующем посещении, вы можете осуществить их предвыборку, при которой они будут загружены в кэш браузера.
Например, если у вас есть блог, а в нём статья из двух частей, вы можете предварительно загрузить статические ресурсы (например, изображения) из второй части, используя предвыборку.
Это делается следующим образом:
<link href="//images.example.com/sept/mypic.jpg" rel="prefetch" />
Веб-альбомы Picasa широко используют предвыборку двух изображений, следующих за текущим. В устаревших браузерах вы можете реализовать это, загружая изображение в JavaScript объект Image:
var i = new Image();
i.src = 'http://images.example.com/sept/mypic.jpg';
Этот код загружает изображение в кэш, но нигде его не использует. Однако этот метод не сработает для файлов CSS и JS, поэтому вам придётся проявить некоторую изобретательность, если вы хотите осуществлять предвыборку таких файлов в устаревших браузерах.
На ум приходит объект XMLHttpRequest: загружайте эти файлы через ajax и не используйте их нигде. В этой статье описано, как это сделать.
Обратите внимание, что предвыборку ресурсов следует использовать только в тех случаях, когда вы уверены или почти уверены, что они потребуются пользователю. Если пользователь читает статью блога, разбитую на страницы, однозначно делайте предвыборку.
Если пользователь заполняет форму, однозначно делайте предвыборку ресурсов, находящихся на странице, на которую он попадёт после отправки формы. Не делайте предвыборку всего вашего сайта или случайных страниц – учитывайте нагрузку на сервер, а также используйте предвыборку умеренно, держа в уме пользователей мобильных устройств.
Мобильные устройства, как правило, имеют ограниченные ресурсы, поэтому предварительная загрузка изображения весом в 2 Мб, вероятно, будет не слишком дружественным к пользователю решением. Вы можете избежать этих проблем, используя селективную предвыборку – определяйте, использует ли пользователь мобильное устройство или медленное соединение, и не используйте предвыборку в этих случаях.
Ещё лучше, добавьте настройки на ваш сайт, и спрашивайте посетителей, согласны ли они использовать предвыборку – сохраняйте их настройки в локальном хранилище и хэшируйте строкой user-agent, тем самым позволяя посетителям разрешать или запрещать предвыборку отдельно на каждом устройстве.
Вы также можете выполнять предвыборку и предварительный рендеринг целых страниц. Предвыборка страниц означает получение DOM контента – кода HTML. Это обычно не даёт существенного выигрыша в скорости, так как большую часть содержимого страницы на самом деле составляют JavaScript, CSS и изображения, то есть контент не загружаемый при предвыборке страницы.
Этот тип предварительной загрузки на данный момент поддерживается только в браузере Firefox.
Предварительный рендеринг – это другой метод. Он поддерживается только в браузере Google Chrome, и не только загружает DOM структуру документа, но и весь соответствующий контент: CSS, Javascript и изображения.
На самом деле, данный метод в фоновом режиме загружает и генерирует страницу целиком – страница помещается в оперативную память полностью загруженной и отрисованной и ожидает вывода на экран.
Это помогает практически моментально осуществлять переход при нажатии на предварительно выбранную ссылку, но порождает проблемы, которые описаны в предыдущем параграфе – страдают пользователи с медленным соединением.
В дополнение к этому, ваш сервер регистрирует предварительно загруженную страницу как посещённую, поэтому вы можете получить несколько неверную статистику посещений, если пользователь на самом деле передумает и не станет открывать эту страницу.
Синтаксис предварительного рендеринга следующий:
<link rel="prerender" href="http://example.com/sept/my-post-part-2">
На данный момент существует только один способ определить, была ли ваша страница предварительно загружена – использовать Page Visibility API, который поддерживается во всех основных браузерах, за исключением браузеров Android и Opera Mini.
Используйте этот API, чтобы определить, действительно ли страница отображается на экране, а затем производите любые записи в статистику, которые вам необходимы.
CSS
Используйте валидатор CSSLint для проверки вашего кода CSS и обнаружения ошибок и потенциальных проблем с производительностью. Прочитайте и соблюдайте правила, приведённые в CSSLint wiki, чтобы писать наиболее эффективный код CSS;
По примеру SQL Explain в базах данных, также существует изящный инструмент CSS Explain. Вы можете использовать его для анализа ваших селекторов CSS. Если вы хотите протестировать данный инструмент в реальном времени, просто вставьте содержимое этого файла в консоль вашего браузера, а затем выполните команду типа;

Сервер
- Оптимизируйте ваш код PHP с помощью простых приёмов
Есть много вещей, которые вы можете предпринять, чтобы повысить быстродействие вашего приложения на уровне PHP. Некоторые простые приёмы описаны в последней статье Фредерика Митчелла.
- Используйте модуль Google PageSpeed
PageSpeed от Google представляет собой модуль, устанавливаемый на Nginx и Apache, который будет автоматически использовать некоторые из лучших приёмов для оптимизации веб-сайта.
Данный модуль оценивает производительность веб-сайта так, как она воспринимается посетителями, следя за исполнением всех правил оптимизации, насколько это возможно, например, улучшая обработку статических ресурсов. Он минимизирует, оптимизирует и сжимает CSS и Javascript файлы за вас, уменьшает размер изображений, удалив ненужные метаданные, устанавливает заголовки Expires для оптимизации кэша браузера и делает многое другое.
А главное – он не потребует от вас никаких изменений в архитектуре. Просто установите его на вашем сервере – и он работает. Чтобы установить модуль, следуйте этим инструкциям – вам нужно будет поработать с исходниками для Nginx, но это всего лишь пара простых команд.
- Используйте SPDY
Для достижения схожих с PageSpeed целей, Google также занимается разработкой SPDY. mod_spdy – это ещё один модуль Apache, созданный для ускорения работы веб-сайта.
Процесс его установки не совсем привычен, а также он требует поддержки в браузере, но с течением времени он совершенствуется.
SPDY – это на самом деле протокол, очень похожий на HTTP, который перехватывает и заменяет запросы HTTP, где это возможно, тем самым увеличивая скорость загрузки сайта. В то время как использование SPDY может быть рискованным, так как мы всё ещё ждём его повсеместной поддержки, выигрыш в скорости, похоже, превосходит риски.
- Используйте формат WebP для изображений
WebP – это формат изображений, претендующий заменить все другие – JPG, PNG и GIF. Он поддерживает альфа-слои (прозрачность), анимацию, сжатие с потерями и без, и многое другое.
Внедрение его поддержки в браузерах продвигается крайне медленно, однако можно легко поддерживать все типы изображений при помощи специального инструмента, вроде автоматического преобразователя WebP, входящего в состав вышеупомянутого модуля PageSpeed (он может автоматически преобразовывать изображения в WebP в реальном времени).
Сжимайте с помощью Zopfli
Используйте сжатие Zopfli, чтобы предварительно сжимать ваши статические ресурсы. Это алгоритм сжатия с открытым кодом, опять же распространяемый Google, который увеличивает сжатие на 3-8% по сравнению с обычными методами сжатия, используемыми в сети.
На маленьких веб-сайтах это вряд ли сыграет ощутимую роль, но если вы расширяете ваше приложение или предоставляете ваш статичный контент большому количеству посетителей, вы определённо заметите разницу, как следует из этого отчёта группы Google Web Fonts.
Заключение
Существует множество способов повысить производительность вашего приложения, и, как и всё в этой жизни – целое больше, чем просто сумма его составляющих. Внедрите некоторые из представленных выше приёмов оптимизации, и вы получите ощутимое улучшение. Внедрите их все – и вы получите настолько быстрое и лёгкое приложение, что оно сможет путешествовать во времени.
Следите за работой своего приложения, используйте HAR, взгляните на профилирование в Dev Tools или подпишитесь на сервис, который будет делать это за вас. Просто не игнорируйте аспекты производительности вашего сайта. В то время как большинство сегодняшних проектов разрабатываются по принципу «сделал и доставил», не оставляйте ваших клиентов с веб-сайтом, которым вы не могли бы гордиться.
Никогда не позволяйте себе недооценивать небольшие исправления, которые вы могли бы сделать. Вы никогда не знаете, какое из них станет последним шагом на пути к совершенству!