webp格式图片的支持情况

webp格式是由Google开发的一种图片格式, 可支持对带透明度或者无透明度的jpg,png,gif等格式的图片进行有损压缩或者无损压缩, 一般来说, 有损压缩可减少25%~34%的体积, 无损压缩可以减少26%左右的体积, 由于需要额外的编解码过程, 所以相比于jpg图片来说编码速度慢10倍, 解码速度慢1.5倍(压缩体积视源文件不同而有所浮动, 解码效率也视运行平台有所浮动, 上面数据是测试的平均值), 但是由于减少了体积, 也就减少了网络传输时间, 总体来说的图片加载完成的时间是要明显短的, 推荐在浏览器支持的情况下使用webp格式图片来代替其他格式, webp兼容情况

webp兼容情况

# 判断客户端是否兼容webp

# 浏览器端

function checkWebp() {
  try {
    return document.createElement('canvas')
      .toDataURL('image/webp')
      .indexOf('data:image/webp') === 0;
  } catch(e) {
    return false;
  }
}

这里利用的浏览器的canvas在导出图片数据时可以自定义导出的图片格式, 如果指定的是浏览器不支持的格式, 那么会被浏览器忽略, 最终得到的是image/png, 所以指定导出image/webp格式, 如果得到的也是这个格式, 那么说明浏览器是支持这个格式的图片的.

注意: 根据caniuse上的数据, 浏览器对canvas.toDataURL('image/webp')方法和webp图片的支持程度不是完全一致的, 对前者支持更晚一些, 也就是说只要是支持canvas.toDataURL('image/webp'), 就一定支持webp, 但是反过来则不正确. 这是一种粗糙但安全的方案.

优点: 同步检测

缺点: 部分老版浏览器实际是支持webp, 但是不支持canvas.toDataURL('image/webp')的, 所以这种判断下会导致少量老版浏览器用户在支持webp的情况下我们认为他用不了, 而让他使用无优化的png或其他图片, 这点损失应该是可以接受的.

「行不行, 试了才知道」, 可以尝试把webp图片给image元素加载, 如果加载成功, 则支持, 加载失败则不支持.

这里给出google开发者文档中的示例代码

// check_webp_feature:
//   'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
//   'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
    var kTestImages = {
        lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
        lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
        alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
        animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
    };
    var img = new Image();
    img.onload = function () {
        var result = (img.width > 0) && (img.height > 0);
        callback(feature, result);
    };
    img.onerror = function () {
        callback(feature, false);
    };
    img.src = "data:image/webp;base64," + kTestImages[feature];
}

优点: webp本身分为有损/无损/透明/动态图, 这种检测可以最精细化的检测到对每种类型是否支持

缺点: 异步检测

# 微信小程序

也有做微信小程序的开发, 而自成体系的小程序在各种方面都很蛋疼, webp的支持也不例外.

微信小程序在ios和android还有开发者工具上采用的是不同的底层框架, 对webp的支持程度也由其底层实现来决定, 所以我们需要分开平台判断

# 服务端判断客户端是否可用webp

浏览器如果支持webp,那么会在特定类型请求的请求头的accept字段附带image/webp标识, 服务器可以判断请求头中是否存在该值.

"特定类型请求"指的是什么?

浏览器会基于请求的上下文来为这个请求头设置合适的值,比如获取一个CSS层叠样式表时值与获取图片、视频或脚本文件时的值是不同的。 --Accept

通常是在htmlimage类型的资源会附带image/xx类型的accept头, 其余的例如css/js/video/audio是不会使用image/xx类型的accept头, 具体的场景可以参考这份文档List of default Accept values, 所以我们可以在html或者image类型资源的请求中来查询accept字段是否附带image/webp标识, 从而判断客户端是否支持webp

accept头字段中的image/webp标识