На одном из сайтов, возникла необходимость внедрить формат изображений webp. Но так как не все браузеры поддерживают данный формат, нужно сделать так, чтобы пользователям, браузеры которых поддерживают этот формат выдавались .webp изображения, а всем остальным jpg/png. Всё это необходимо было сделать на связке nginx+php-fpm. Так как я не системный администратор, то обратился на фриланс, чтобы помогли мне в этом. А готовым решением, решил здесь поделится (вдруг кому-то понадобится).
Для того, чтобы всё заработало, нам нужно немного отредактировать только 2 файла NGINX:
Читайте также: Настраиваем NGINX для Opencart, через ISPmanager
- Глобальный конфигурационный файл: /etc/nginx/nginx.conf
- Конфигурационный файл самого домена: /etc/nginx/vhosts/login/site.com.ua.conf
В первый файл добавляем:
map $http_accept $image {
default 0;
"~*image/webp,*/*" "1";
}
Во второй:
if ($image) {
rewrite ^(.*)\.(jpg|jpeg) $1.webp last;
}
В итоге, глобальный конфигурационный файл, у меня выглядит так:
user apache;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
# Метод выбора соединений (для FreeBSD будет kqueue)
use epoll;
# Принимать максимально возможное количество соединений
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# Отключить вывод версии nginx в ответе
server_tokens off;
access_log /var/log/nginx/access.log main;
sendfile on;
# Ограничивает объём данных, который может передан за один вызов sendfile(). Нужно для исключения ситуации когда одно соединение может целиком захватить воркер
sendfile_max_chunk 128k;
# Отправлять заголовки и и начало файла в одном пакете
tcp_nopush on;
tcp_nodelay on;
# Сбрасывать соединение если клиент перестал читать ответ
reset_timedout_connection on;
# Разрывать соединение по истечению таймаута при получении заголовка и тела запроса
client_header_timeout 3;
client_body_timeout 5;
# Разрывать соединение, если клиент не отвечает в течение 3 секунд
send_timeout 3;
# Задание буфера для заголовка и тела запроса
client_header_buffer_size 2k;
client_body_buffer_size 256k;
# Ограничение на размер тела запроса
client_max_body_size 128m;
#tcp_nopush on;
#gzip on;
map $http_accept $image {
default 0;
"~*image/webp,*/*" "1";
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/vhosts/*/*.conf;
server {
server_name localhost;
disable_symlinks if_not_owner;
listen 80;
listen [::]:80;
include /etc/nginx/vhosts-includes/*.conf;
location @fallback {
error_log /dev/null crit;
proxy_pass http://127.0.0.1:8080;
proxy_redirect http://127.0.0.1:8080 /;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
access_log off ;
}
location ~ \.php$ {
try_files $fastcgi_script_name =404;
fastcgi_index index.php;
fastcgi_param script_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
}
}
И конфигурация домена для opencart (использую ISPmanager) так:
server {
server_name site.com.ua www.site.com.ua;
rewrite ^ https://site.com.ua$request_uri? permanent;
charset off;
index index.html index.php;
disable_symlinks if_not_owner from=$root_path;
include /etc/nginx/vhosts-includes/*.conf;
include /etc/nginx/vhosts-resources/site.com.ua/*.conf;
#return 301 https://$host:443$request_uri;
return 301 https://site.com.ua$request_uri ;
error_log /dev/null crit;
set $root_path /var/www/login/data/www/site.com.ua;
root $root_path;
gzip on;
gzip_comp_level 9;
gzip_disable "msie6";
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
if ($image) {
rewrite ^(.*)\.(jpg|jpeg) $1.webp last;
}
location / {
location ~* ^.+\.(webp|jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf|woff2)$ {
expires 365d;
}
rewrite ^/sitemap.xml$ /index.php?route=feed/google_sitemap last;
rewrite ^/googlebase.xml$ /index.php?route=feed/google_base last;
rewrite ^/system/download/(.*) /index.php?route=error/not_found last;
if (!-f $request_filename){
set $rule_3 1$rule_3;
}
if (!-d $request_filename){
set $rule_3 2$rule_3;
}
if ($uri !~ ".*.(jpg|jpeg|ico|gif|png|js|css)"){
set $rule_3 3$rule_3;
}
if ($rule_3 = "321"){
rewrite ^/([^?]*) /index.php?_route_=$1 last;
}
location ~ [^/]\.ph(p\d*|tml)$ {
try_files /does_not_exists @php;
}
location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf|woff2)$ {
expires 365d;
}
}
location ~ [^/]\.php(/|$) {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f [email protected]";
fastcgi_pass unix:/var/www/php-fpm/login.sock;
fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
try_files $uri =404;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
}
ssi on;
location @php {
fastcgi_index index.php;
fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f [email protected]";
fastcgi_pass unix:/var/www/php-fpm/login.sock;
fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
try_files $uri =404;
include fastcgi_params;
}
rewrite ^/zapchasti-dlia-smartfonov/ekrany-i-sensory/(.*)$ https://site.com.ua/zapchasti-dlia-smartfonov/lcd-displays/ permanent;
rewrite ^/uk/zapchasti-dlia-smartfonov/ekrany-i-sensory/(.*)$ https://site.com.ua/uk/zapchasti-dlia-smartfonov/lcd-displays/ permanent;
return 301 https://$host:443$request_uri;
access_log off;
listen 185.156.56.43:80 default_server;
}
server {
server_name site.com.ua www.site.com.ua;
if ($host ~* ^www.site.com.ua$) {
return 301 $scheme://site.com.ua$request_uri;
}
ssl on;
ssl_certificate "/var/www/httpd-cert/login/site.com.ua_le1.crtca";
ssl_certificate_key "/var/www/httpd-cert/login/site.com.ua_le1.key";
ssl_ciphers EECDH:+AES256:-3DES:RSA+AIS:!NULL:!RG4;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
add_header Strict-Transport-Security "max-age=31536000;";
ssl_dhparam /etc/ssl/certs/dhparam4096.pem;
charset off;
index index.html index.php;
disable_symlinks if_not_owner from=$root_path;
include /etc/nginx/vhosts-includes/*.conf;
include /etc/nginx/vhosts-resources/site.com.ua/*.conf;
error_log /dev/null crit;
ssi on;
set $root_path /var/www/login/data/www/site.com.ua;
root $root_path;
gzip on;
gzip_comp_level 9;
gzip_disable "msie6";
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
if ($image) {
rewrite ^(.*)\.(jpg|jpeg) $1.webp last;
}
location / {
location ~* ^.+\.(webp|jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf|woff2)$ {
expires 365d;
}
rewrite ^/sitemap.xml$ /index.php?route=feed/google_sitemap last;
rewrite ^/googlebase.xml$ /index.php?route=feed/google_base last;
rewrite ^/system/download/(.*) /index.php?route=error/not_found last;
if (!-f $request_filename){
set $rule_3 1$rule_3;
}
if (!-d $request_filename){
set $rule_3 2$rule_3;
}
if ($uri !~ ".*.(jpg|jpeg|ico|gif|png|js|css)"){
set $rule_3 3$rule_3;
}
if ($rule_3 = "321"){
rewrite ^/([^?]*) /index.php?_route_=$1 last;
}
location ~ [^/]\.ph(p\d*|tml)$ {
try_files /does_not_exists @php;
}
}
location @php {
fastcgi_index index.php;
fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f [email protected]";
fastcgi_pass unix:/var/www/php-fpm/login.sock;
fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
try_files $uri =404;
include fastcgi_params;
}
access_log off;
listen 185.156.71.55:443 ssl default_server http2;
}
Теперь же, браузерам которые выдают заголовок, что поддерживают .webp выдаются изображения .webp, а если нет, то jpg.