liveKang / Blog

my person blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

webp H5移动端实战总结

liveKang opened this issue · comments

webp H5移动端实战总结

Isabella Scherer

对于移动端优化来说,图片大小是不可忽视的一部分,png, jpg, jpeg, gif, sprites, PS 先导出 web 格式压缩品质,前端构建工具压缩,服务端对图片进行再次压缩,甚至采用某某小道的极致压缩等等,都没能达到期望的效果。为此 webp(谷歌官方地址) 实战部署的想法,应运而生。

解决方案

方案一

服务端根据浏览器Request Headers中的Accept 判断是否有 image/webp,有则代表该浏览器支持webp格式的图片,无则不支持,返回原图,适用于整站图片处理。难点在运维同学需要处理下。前端同学给大佬送茶即可。

方案二

服务端根据图片的请求尾缀生成 webp 。

首先前端检测该浏览器是否支持 webp 。

方法比较多,这边列举一种加载一个小 webp 图片的方案。

var img = new Image();
img.onload = function () {
    var result = (img.width > 0) && (img.height > 0);
    console.log("当前浏览器支持webp");
};
img.onerror = function () {
    console.log("当前浏览器不支持webp");
};
img.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';

例如一张原图地址https://m.pinhui001.com/dist_css/img/index-foreign.jpg,如果浏览器支持webp,则在图片的后面加上.webp的尾缀。如https://m.pinhui001.com/dist_css/img/index-foreign.jpg.webp,反之则不加。这种方案是由前端控制是否需要 webp 格式图片,需要就由服务端生成,每张图片第一次访问时会立即生成一张 webp 图片。会需要一定的生成时间。

我们使用的是nginx容器发布。可以采用 Nginx-Lua 自动转换图片为 WEBP 格式。

  1. 安装 libwebp

    通过包管理安装 libwebp

    pacman -S libwebp

    手动安装

    wget "http://downloads.webmproject.org/releases/webp/libwebp-0.5.0-linux-x86-64.tar.gz" tar --strip-components 1 -xzvf libwebp*.gz -C /usr/local

    这样我们就会有了 libwebp 和 "cwebp" 命令来方便的编码图片

  2. 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
     
     os.execute("cwebp -q 75 " .. originalFile  .. " -o " .. newFile);   -- 转换原图片到 webp 格式,这里的质量是 75 ,你也可以改成别的
     
     if file_exists(newFile) then -- 如果新文件存在(转换成功)
         ngx.exec(ngx.var.uri) -- Internal Redirect
     else
         ngx.exit(404)
     end
     
  3. Nginx 配置

    在Http块中加入

     lua_package_path "/usr/local/openresty/nginx/conf/lua/?.lua;"; # 指向存放 lua 代码的路径
     

    server 块中加入一个 location

     location /images {
       expires 365d;
       try_files $uri $uri/ @webp; # 如果文件不存在尝试生成 webp 图片
     }
     location @webp{
       if ($uri ~ "/([a-zA-Z0-9-_]+)\.(png|jpg|gif)\.webp") { # 这里可以改成你自己的路径匹配,很重要,否则可能会导致别的文件被恶意覆盖等
         content_by_lua_file "/usr/local/nginx/conf/waf/webp.lua";
       }
     }
     

方案三

公司的图片库动辄几百上千G,如果要全面启用 webp,如果有一定困难的话,我们也是可以局部使用 webp 的,前端自己生成 webp 图片,我们应用的是静态资源部分的图片。这里以 gulp 为例,描述下前端如何生成 webp图片。

gulp 中有一个模块 gulp-webp,该模块依赖了 imagemin-webp。代码如下,比较简单,生成的速度也比较快。与静态资源一并上传到生产就可以使用了。

gulp.task('webp', function() {
    return gulp.src(Config.img.src)
	    .pipe(webp({
	        quality: 75
	    }))
	    .pipe(flatten())
	    .pipe(gulpif(!ifProd,gulp.dest(Config.img.dist)))
	    .pipe(gulpif(ifProd,gulp.dest(Config.img.dist_prod)));
});

总结

移动端流量优化中图片优化,webp带来的优势相当明显。

附录

webp图片适配流量优化(推荐阅读)

对我以上的理解有疑问和意见的欢迎找我私聊~