提醒:本文最后更新于 2750 天前,文中所描述的信息可能已发生改变,请仔细核实。

Nginx对图片的处理,可以利用其对Lua支持(需要lua nginx module)来实现。
今天介绍有关将图片压缩为webp的方法。webp的好处可以自行搜索。
首先,需要准备带有lua nginx module的Nginx,以及libwebp库。
Nginx添加lua nginx module的方法不再表,具体可以参考之前文章《我的Nginx编译之旅》。
关于libwebp,可以通过包管理或其官网安装,官网传送门。注意需要Glibc版本不小于2.14。
接着,创建Lua脚本文件,比如名字为cwebp.lua(Lua脚本名),放在你知道的位置上(我喜欢放在Nginx的配置目录下),内容如下:
--------------------------- Function ---------------------------------
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
------------------------------------------------------------------------
if ngx ~= nil then
local reqpath = ngx.var.request_filename;
local requri = ngx.var.uri;
local originalFile = reqpath:sub(1, #reqpath - 13);
local originalFile_uri = requri:sub(1, #requri - 13);
if not file_exists(originalFile) then
ngx.exit(404);
return;
end
local newFile_md5 = ngx.md5(originalFile_uri);
local newFile = ngx.var.document_root .. "/wp-content/webp/" .. newFile_md5 ..".webp";
local newFile_uri = "/wp-content/webp/" .. newFile_md5 .. ".webp";
if file_exists(newFile) then
ngx.req.set_uri(newFile_uri);
ngx.exec(ngx.var.uri);
return;
end
os.execute("cwebp -quiet " .. originalFile .. " -o " .. newFile);
if file_exists(newFile) then
ngx.req.set_uri(newFile_uri);
else
ngx.req.set_uri(originalFile_uri);
end
ngx.exec(ngx.var.uri);
end
以上为我按照自己需求做的一个lua脚本,这个脚本的流程是这样的:
1.首先去除
!/format/webp的后缀,共计13个字符。
2.如果源文件不存在,返回404并结束。
3.对请求的URI进行md5处理并作为webp文件名,新文件位于根目录下的/wp-content/webp目录下(请按自己需求更改)。
4.如果新文件存在,那么返回该文件内容并结束。不存在的话,调用libwebp库的cwebp程序对图片进行处理。
5.检查webp文件是否被创建,如果存在返回webp文件内容,不存在则返回源文件内容。
如果你是第一次使用Lua,需要在Nginx的http段,添加Lua脚本位置注册:
lua_package_path '/usr/local/nginx/conf/lua/?.lua;;';
其中/usr/local/nginx/conf/lua/为你未来lua脚本文件归置的目录。如果你存放于Nginx默认索引的Lua目录下,可以忽略此步。
你可以根据实际情况,选择是否启用lua_code_cache。
最后,在Nginx的server段,添加对!/format/webp请求进行回应,指定由cwebp.lua来处理。
location ~ \!/format/webp$ {
expires max;
content_by_lua_file "/usr/local/nginx/conf/lua/cwebp.lua";
}
其中/usr/local/nginx/conf/lua/cwebp.lua为上面创建的cwebp.lua绝对路径,注意它位于注册的Lua归置目录下。
如果你像我一样,也有使用headers more nginx module,那么你可以添加多一句:
more_clear_headers "Set-Cookie*";
来去除图片请求中不必要的cookie传输。
保存后,reload或restart Nginx即可。
php上理论可以通过以下判断浏览器是否支持webp,以此来决定是否为图片添上webp转换后缀。
function browser_is_support_webp(){
return isset($_SERVER['HTTP_ACCEPT']) ? strstr($_SERVER['HTTP_ACCEPT'],'image/webp') : FALSE;
}
像Wordpress的话,可以利用Wordpress的原生filter:the_content,以及正则函数来达到hook目的。
转载请注明转自: kn007的个人博客 的《为Nginx添加将图片转换成WebP支持》

更新至 Nginx 级 WebP 生成
@lwl12:
语文学得不错
先占坑 让我看看这次更新了啥
@一曲长歌辞烟雨: 没有更新,很久很久以前的配置。
啊,终于知道了 libwebp 的用法(摊
@metowolf: 额
其实还蛮好用
Webp还是有必要的, 不晓得apache是否也有相似的处理方法, 话说google不是有pagespeed么.
@Sam.Z: apache忘得一干二净。
我不用pagespeed。
伺服器:該加工資了
@Kreen: 早給足了金錢
ho to translate this page
@karen: Maybe you could try google translation
你的nginx真牛!有空了跟着你的整一整
@ayawaw: 没什么牛不牛的,以前就是这样,没进步一直
试了一下好像不行诶,Nginx返回404,不清楚是什么情况,Nginx日志也没错误啊,真是纳闷。路径已经改了,也不是权限问题,Lua文件的权限是777啊,也不应该不能执行啊.....emmmm
大佬可以帮忙看看吗?
https://t.me/haimaAS1
@海马: 404无非两种原因啊,第一种源文件不存在,第二种,压根nginx没对后缀hook调用lua。
把nginx日志等级调一下就能看到原因了。或者把代码中唯一的404改成其他状态码,也能确认。
好久不见,学习了
@咕噜噜: 我是经常访问啊,但是每次都是建设中

@kn007: 我真是讨厌自己,感觉建设好几年了
不过说真的,昨天留言的时候,我还没有下班……
@咕噜噜: 能者多劳,看来喜提金砖!
@kn007: 能者多劳,勤奋工作,终助老板喜提金砖
This is so much easier.
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
location ~* ^.+\.(jpe?g|png) {
try_files $uri$webp_suffix $uri =404;
expires max;
}
for x in `find /var/www/itchy -type f \( -iname \*.jpeg -o -iname \*.jpg -o -iname \*.JPG -o -iname \*.png \)`
do cwebp -quiet -q 80 ${x} -o ${x}.webp;
echo "Converted $x to ${x}.webp"
done