为Nginx添加将图片转换成WebP支持

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


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支持