четверг, 17 августа 2017 г.

Отдаем .webp вместо jpg/png при помощи .htaccess

Формат .webp уже поддерживается основными браузерами: файрфоксом, эджем, хромом и аналогами, их совокупная доля на рынке превышает 75%, а значит есть смысл его использовать, чтобы изображения быстрее загружались.

Как это сделать? Существуют решения с <picture> или определением поддержки webp при помощи джаваскрипта, добавлением класса .webp в <html> и загрузки нужных форматов через css. Эти варианты требуют изменения разметки. Вместо этого можно обойтись всего лишь изменением конфига сервера.

Работает так:
  1. Сервер проверяет, поддерживает ли браузер пользователя webp (браузер указывает в это заголовках запроса).
  2. Если пользователь запрашивает изображение, то сервер проверяет, есть ли такая же картинка с расширением webp.
  3. Если есть, то отдает ее пользователю. Иначе отдает обычную.
Решение для .htaccess:

В диспетчере запросов будет виден только один запрос с изначальной картинкой, вместо которой будет отдан webp файл. В столбце Type будет указано "webp".

Существуют аналогичные решения: webp-detect (заодно есть конфиг для nginx и др.), WebP-images-with-htaccess.

Их особенность в том, что они не работают. В них для проверки существования файла с расширением webp используется {DOCUMENT_ROOT}, но у меня он ведет в корень сайта, а не в папку с файлом. Из-за этого сервер не может найти webp файлы. Зато вариант с {REQUEST_FILENAME} работает.

Вывести переменную из .htaccess

При отладке .htaccess хочется вывести на экран значение переменных или найденных строк. На stackoverflow есть решение:
# в переменную окружения TEST0 передаем требуемые данные
RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

# после чего показываем эту переменную в заголовке ответа TEST_FOOBAR
Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"
Например, если мы хотим отладить отдачу картинок webp через .htaccess, то делаем так:
<IfModule mod_rewrite.c>
  RewriteEngine On

  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_FILENAME} ^(.+)\.(jpe?g|png)$
  RewriteCond %1\.webp -f
    RewriteRule ^(.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1,E=TEST0:%1\.webp]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
  Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"
</IfModule>

AddType image/webp .webp
Затем заходим в инспектор запросов браузера, кликаем на нужный запрос, и смотрим заголовок TEST_FOOBAR:



Более подробное логирование

В апаче можно включить логирование rewrite-правил: он будет объяснять что делает и почему. Но, к сожалению, такой лог нельзя включить через .htaccess, а значит на обычных хостингах работать не будет. Впрочем, можно включить его на своем локальном апаче и отладить там.

Он включается в настройках VirtualHost апача. Нужно указать:
LogLevel alert rewrite:trace8
Перезапускаем апач и теперь в error.log будет отображаться подробная информация по правилам .htaccess.