一般商品主图大小为800800(淘宝)或者750750(京东),即便以72*72的分辨率去做图,图片的大小也有几百k,对于移动端而已,图片过大,加载过慢,于是研究了下用Nginx和Lua进行图片webp压缩处理。以下我主要参考的几篇文章:
通过 Nginx-Lua 自动转换图片为 WebP 格式
nginx 之前端图片webp
centos yum 安装nginx 后增加模块
centos-nginx添加模块(无需重新编译)
下面进入正题:
wget "http://downloads.webmproject.org/releases/webp/libwebp-0.6.0-linux-x86-64.tar.gz"
tar --strip-components 1 -xzvf libwebp*.gz -C /usr/local
测试是否安装成功
cwebp -q 75 test.png -o test.png.webp
由于我本来就已经安装好了nginx,也不便停用,故只能为nginx添加lua模块。如果是全新安装nginx的同学,建议直接安装OpenResty,里面集成了nginx和lua。以下开始安装:
cd /root
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.11.zip
unzip v0.10.11.zip
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.zip
unzip v0.3.0.zip
wget http://luajit.org/download/LuaJIT-2.0.5.zip
unzip LuaJIT-2.0.5.zip
cd LuaJIT-2.0.5
make
make install PREFIX=/usr/local/luajit
cat > /etc/ld.so.conf.d/luajit.conf<
由于我是用yum安装的nginx,查看现在的nginx版本,然后再重新编译。
nginx -V
nginx version: nginx/1.14.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
于是下载1.14.0版本:
$ wget http://nginx.org/download/nginx-1.14.0.tar.gz
$ tar xvzf nginx-1.14.0.tar.gz
然后重新编译
cd nginx-1.14.0
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-module=/root/lua-nginx-module-0.10.11 --add-module=/root/ngx_devel_kit-0.3.0
$ make #千万别make install,否则就覆盖安装了
#备份旧的nginx程序
$ cp /usr/sbin/nginx /usr/sbin/nginx.bak
#把新的nginx程序覆盖旧的
$ cp objs/nginx /usr/sbin/nginx
#重启nginx
$ sudo systemctl restart nginx.service
新建webp.lua文件
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
local newFile = ngx.var.request_filename;
local originalFile = newFile:sub(1, #newFile - 5); -- 去掉 .webp 的后缀
if not file_exists(originalFile) then -- 原文件不存在
ngx.exit(404);
return;
end
local cmdstr = "cwebp -q 20 " .. originalFile .. " -o " .. newFile; -- 转换原图片到 webp 格式,这里的质量是 20, 压缩比例为90%
cmdstr = string.gsub(cmdstr,"%$","\\$"); -- 处理字符串中含有dollar符号的
os.execute(cmdstr);
if file_exists(newFile) then -- 如果新文件存在(转换成功)
ngx.exec(ngx.var.uri) -- Internal Redirect
else
ngx.exit(404)
end
如果文件名中有$符号
修改img.conf配置,在server中添加
# webp 压缩
location ~* ^(.+\.(jpg|jpeg|gif|png))\.webp$ {
set $webp_root /mnt/www/img;
root $webp_root;
set $filename $webp_root$uri;
if (!-f $filename) {
set $request_filepath $webp_root$1;
content_by_lua_file "/etc/nginx/conf.d/webp.lua";
}
}
重启nginx即可访问了。
经过上面的一波操作,我们终于可以使用webp压缩了。 不过,可惜的webp的google的标准,由于我们的图片要使用在微信小程序上,而iphone的微信小程序内置的浏览器不支持webp格式。于是只能放弃webp,下面使用的是GraphicsMagick压缩方式来替代。
wget https://nchc.dl.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.31/GraphicsMagick-1.3.31.tar.xz
xz -d GraphicsMagick-1.3.31.tar.xz
tar -xvf GraphicsMagick-1.3.31.tar
cd GraphicsMagick-1.3.31
./configure
make
make install
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
local gmReqFile = ngx.var.request_filename; -- 原来访问地址
local originalFile = string.gsub(gmReqFile, "gm/",""); -- 去掉 gm 文件夹
local gmDir = string.match(originalFile, "(.+)/[^/]*%.%w+$") .. "/gm"; -- gm目录
--local imgName = string.match(originalFile, ".+/([^/]*%.%w+)$"); -- 文件名带原本的后缀
local imgName = string.match(originalFile, ".+/([^/]*)%.%w+$"); -- 文件名,无后缀
local gmFile = gmDir .. "/" .. imgName .. ".jpg"; -- 最终访问文件, 全部转为jpg
if file_exists(gmFile) then -- 如果压缩图已经存在
ngx.exec(string.gsub(ngx.var.uri, "png","jpg"))
--ngx.exec(ngx.var.uri)
end
if not file_exists(originalFile) then -- 原文件不存在
ngx.exit(404);
return;
end
local response = os.execute("cd " .. gmDir) -- 如果gm文件夹不存在
if response ~= 0 then
os.execute("mkdir -p " .. gmDir);
end
local cmdstr = "gm convert -quality 75% " .. originalFile .. " " .. gmFile; -- 转换质量 75 % ,由于不同图片色彩不一样,压缩比例会不同,30%到90%
cmdstr = string.gsub(cmdstr,"%$","\\$"); -- 处理字符串中含有dollar符号的
os.execute(cmdstr);
if file_exists(gmFile) then -- 如果新文件存在(转换成功)
ngx.exec(string.gsub(ngx.var.uri, "png","jpg"))
--ngx.exec(ngx.var.uri)
else
ngx.exit(404)
end