什么是 webp这里就不在赘述,不懂的童鞋直接百度。
需要实现功能:
- 不改变现有网站结构的情况下实现对webp的支持。
- 生成缓存web文件夹,不用每次访问都重新生成,提高效率。
逻辑思考:
- 浏览器发起请求,nginx localtion拦截请求。
- 转发到lua脚本,lua脚本处理图片转换成 webp(生成缓存)。
- 处理完成返回新生成的图片。
思路分析完成,开干。
没有nginx的先安装nginx
sudo apt-get install nginx-full
安装lua及相关组件(此项非必须,根据需求安装)
apt-get install lua5.2 lua5.2-doc liblua5.2-dev
安装luajit
sudo apt-get install luajit
关于JIT :
通常,程序有两种运行方式:静态编译与动态直译。
静态编译的程序在执行前全部被翻译为机器码,而动态直译执行的则是一句一句边运行边翻译。
即时编译(Just-In-Time Compiler)则混合了这二者,一句一句编译源代码,但是会将翻译过的代码缓存起来以降低性能损耗。
此外,使用luajit可以大大提高lua的运行效率,由此也被官方钦定。
安装nginx的lua模块 lua-nginx-module(重点是这个 nginx扩展API)
sudo apt-get install libnginx-mod-http-lua
如果出现找不到源的情况,请根据自己系统版本在ubuntu官方源寻找,修改source.list文件,增加支持。
官方源库地址:官方地址,进入官方源库地址,选择自己的系统版本,搜索软件名即可。
感谢这位大佬的安装说明:https://www.centos.bz/2017/09/debianubuntu-%E4%B8%8B-nginxlua-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/
注:楼主ubuntu 18.04系统在安装的时候出现安装成功但无法识别的情况:unknown device content_by_lua_file ,解决方案卸载 nginx 重新安装即可,或者升级nginx1.16, 系统默认是1.14.
安装webp命令
apt install webp
配置nginx
nginx的配置中,核心在于content_by_lua_file。
关于 content_by_lua_file 的官方文档: https://github.com/openresty/lua-nginx-module#content_by_lua_file
本人的配置代码供参考:
location ~ \.(gif|jpg|jpeg|png|bmp) {
if (!-e $request_filename) { #如果文件不存在直接返回404
return 404;
}
expires 30d;
if ( $http_accept ~* '(image/webp)' ){ #判断来源设备是否支持webp
set $tmppath "/temp_webp/"; #设置缓存路径,分2个变量脚本里面需要
set $tmp $document_root$tmppath; # 设置绝对路径缓存地址 缓存目录请勿必给权限,不然报错
content_by_lua_file "/etc/nginx/webp.lua"; #脚本存放位置勿必给执行权限
}
}
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 originalFile = ngx.var.request_filename; --原文件地址
local tmpFile =ngx.var.tmp .. ngx.md5(originalFile) .. '.webp'; --缓存 webp文件地址(绝对路径)
local tmpPathFile =ngx.var.tmppath .. ngx.md5(originalFile) .. '.webp'; --缓存webp文件路径(相对路径),后续返回
if file_exists (tmpFile) then --判断是否有缓存文件,有就直接输出
return ngx.exec(tmpPathFile);
end
if not file_exists(originalFile) then -- 原文件不存在
return ngx.exit(404);
end
executeCmd = "/usr/bin/cwebp -q 80 " .. originalFile .. " -o " .. tmpFile
os.execute(executeCmd); -- 转换原图片到 webp 格式,这里的质量是 75 ,你也可以改成别的
if file_exists(tmpFile) then -- 如果新文件存在(转换成功)
return ngx.exec(tmpPathFile) -- Internal Redirect
else
---------------------
return ngx.exit(404)
end
测试
转成webp图片后:
未转成webp图片:
webp大小为:144KB ,png大小:453KB 。