2

圭多·雷尼_Aurora

原文地址:https://segmentfault.com/a/1190000038458838
作者:Fw恶龙
本文首发于:思否

一、前言

关于 WebP 的支持情况,以及适用场景此处不做详细说明,具体见官方文档

先说结论,目前 WebP 支持情况占比较大(数据如下),在适合的场景下可以使用 WebP 格式图片来提高页面加载速度。

  • 支持的浏览器占比达到近90%(数据来源:Can I Use
  • 安卓系统下大部分浏览器已支持,而安卓系统在国内移动端系统中占比达80%(数据来源:statcounter
  • iOS14+ 已经支持 Webp 格式。Added WebP image support.

目前使页面支持 WebP 格式图片有两种方式:

  • 前端开发过程生成对应格式图片并编写 WebP 相关代码(本文介绍)
  • 服务器端支持生成 WebP 格式图片,前端编写相关加载代码(这部分未深入研究)

二、压缩效果

设置压缩质量为81时,可以在尺寸和质量两者间取得较好的平衡。(测试结果与图片类型以及色彩丰富度有关,具体的压缩质量可以根据实际情况自行调整)

三、在开发中如何使用?

1. html

<picture> 标签会根据浏览器支持情况加载对应资源。

<picture>
    <source srcset="./webp/demo.webp" type="image/webp">
    <img src="./images/demo.png"/>
</picture>

2. css

通过 js 检测当前浏览器是否支持 WebP 格式的图片(细节见下文 js 代码),在 html 标签上动态添加类名 webp/no-webp,根据浏览器支持情况加载不同格式的图片。

.box {
    width: 5.73rem;
    height: 6.57rem;
    background-repeat: no-repeat;
    background-size: 100% 100%
}

.no-webp .box {
    background-image: url(../images/demo.png);
}

.webp .box {
    background-image: url(../webp/demo.webp)
}

3. js

通过创建 canvas 标签生成 WebP 格式图片,根据其是否生成成功,来判断浏览器是否支持 WebP 格式的图片。

var isSupportWebp = function () {
    if(document.createElement('canvas').toDataURL('image/webp', 0.5).indexOf('data:image/webp') === 0) {
        document.getElementsByTagName('html')[0].classList.add('webp');
        console.warn("No support webp");
    } else {
        document.getElementsByTagName('html')[0].classList.add('no-webp');
        console.warn("Support webp");
    }
}

isSupportWebp();

20201221 更新

Firefox 65 与 iOS 14+ 已经支持 webp 格式,但是以上方法仍然返回 false,故采用官方提供的方法(异步)

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];
};

check_webp_feature('lossy', function(type, support) {
    if(support) {
        document.getElementsByTagName('html')[0].classList.add('webp');
        console.info('Support webp ' + type);
    } else {
        document.getElementsByTagName('html')[0].classList.add('no-webp');
        console.warn('No support webp ' + type);
    }
});

四、开发流程

以下流程仅提供大致思路,具体的 webpack 相关配置会根据项目有所出入。

  1. 设计稿产出 jpg/png 格式切片
  2. 开发过程使用 webpack 插件 imagemin-webp-webpack-plugin 根据切片自动生成 WebP 格式的切片
  3. html 底部引入上文对应的 js 检测代码
  4. html 中的 <img> 标签改为使用 <picture> 标签
  5. css 通过预处理器封装背景相关样式的函数,以下为 stylus 代码

    bg-webp($url, $ext = png)
        .no-webp &
            background-image url($baseUrl + $url + "." + $ext)
        .webp &
            background-image url($baseUrlWebp + $url + ".webp")

五、注意事项

1. 以下使用方式会导致 WebP 图片变大

  • 引入渐进式的 jpg/png 格式的图片(WebP 不支持渐进式格式)
  • 引入已经压缩过的图片(webpack 无法判断该图片是否压缩过)

2. 使用场景

适合

  • 较大的图片,如:背景图

不适合

  • 小图不建议使用,差别不大
  • canvas 等合成图片的还未尝试,因涉及跨域、兼容性等问题,暂时不使用

六、相关文档


Fw恶龙
276 声望46 粉丝

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视。