kn007的个人博客
♥ You are here: Home > 软件与网络 > php > 为Nginx添加将图片转换成WebP支持

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

by | 35 Comments

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


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

donate
有所帮助?

Comments

35 Comments立即评论
  1. 早就没图了!懒得放

    1. MOD回复
  2. 服务器支持是Lua,但在WordPress这边是需要插件什么来实现的吗……

    1. MOD回复

      @云间守望: filter

    2. @kn007: 最后使用了PageSpeed……
      https://www.modpagespeed.com/

    3. 回复

      @云间守望: 这玩意贼方便

  3. 回复

    学习了

  4. 已经很认真在看。

  5. 现在几乎所有的CDN都支持这个格式的转换了好像! :smile:

  6. 技术文章,了解下就行了,折腾不会。还是老老实实传jpg :o

  7. =、= 为何要自己安装 Nginx Lua Module,如果是我,选择用 Openresty,春哥出品。 :cry: :cry: :cry:

    1. MOD回复

      @雨帆: 因为Openresty的nginx版本更新太慢了。
      而且Lua module是春哥的啊

  8. 回复

    实在折腾不来,只好用插件搞。 :|

icon_wink.gificon_neutral.gificon_mad.gificon_twisted.gificon_smile.gificon_eek.gificon_sad.gificon_rolleyes.gificon_razz.gificon_redface.gificon_surprised.gificon_mrgreen.gificon_lol.gificon_idea.gificon_biggrin.gificon_evil.gificon_cry.gificon_cool.gificon_arrow.gificon_confused.gificon_question.gificon_exclaim.gif