seven's blog | 网页性能提升之WebP

网页性能提升之WebP
2019年05月21日

鉴于之前做的大屏的项目,全屏背景图过大,传统的写法导致页面渲染过慢,因而非常影响用户体验。

除此以外,很多时候在开发过程中会出现很多图片的情况,图片过多或大,会直接影响页面的响应时间,从而导致页面性能变差。

针对以上,我们可以使用WebP来有效的改善。

关于WebP

WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间。
WebP既支持有损压缩也支持无损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更少的计算资源。

优势

  • 图片体积更小的情况下,图像质量不变
  • 具有alpha透明和动画特性
  • 更优的图像数据压缩算法

兼容性

webp兼容性 目前Chrome、Oprea以及较高版本的火狐等是支持WebP的,其实这个数量也一直在增加,未来可能会有更好的兼容性。

不过就目前来看,在使用webp的同时,还是需要对其不兼容的情况进行处理的

WebP在项目中的使用

格式转换

我之前是在下面这个网站进行手动转换的: https://www.upyun.com/webp

还有一些其他的工具(智图isparta),当然我们也可以借助google的官方工具

检测平台是否支持webp格式

1.检测浏览器是否支持webp的图片格式,如果支持,就返回true,否则返回false
function checkWebp() {
    try{
        return (document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0);
    }catch(err) {
        return  false;
    }
}

console.log(checkWebp());
2.来自官网
// 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,那么图片的宽高会大于0,从而返回true,否则返回false.

使用方法:

第一个参数feature可以传 lossy,lossless,alpha,animation中的一个,第一个传个回调函数。获取他result。如果支持,返回ture,否则返回false。可以再谷歌和IE下试试,谷歌返回ture,IE返回false

check_webp_feature('lossless',function(feature,result){
    alert(result); //true or false
});
3.加载一张webp图片,如果可以加载出来,那么就是支持webp,否则就是不支持。如果支持webp,那么给html加一个class 叫 webps。
;(function(doc) {

    // 给html根节点加上webps类名
    function addRootTag() {
        doc.documentElement.className += "webps";
    }

    // 判断是否有webps=A这个cookie
    if (!/(^|;\s?)webps=A/.test(document.cookie)) {
        var image = new Image();

        // 图片加载完成时候的操作
        image.onload = function() {

            // 图片加载成功且宽度为1,那么就代表支持webp了,因为这张base64图是webp格式。如果不支持会触发image.error方法
            if (image.width == 1) {

                // html根节点添加class,并且埋入cookie
                addRootTag();
                document.cookie = "webps=A; max-age=31536000; domain=58.com";
            }
        };

        // 一张支持alpha透明度的webp的图片,使用base64编码
        image.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==';
    } else {
        addRootTag();
    }
}(document));

如何使用

1. 纯手动

因为之前的项目需要用到的图片不是很多,所以我就采用了最傻瓜也是最直接的使用方法,在类中多写一个webp格式的背景图样式: image 这样的写法,对于兼容webp的浏览器,会引用下方的webp背景图,对于不兼容的,则显示上方jpg格式的图片。不会因为兼容问题导致图片不显示。

不过这种方法不够灵活,只针对项目中出现少数大图需要处理时使用。减少其他配置所浪费的时间。

可以看到下面两个图的对比,使用了webp的图片响应速度还是快乐不少的。

image image

scss配置

如果项目使用了scss,也可以编辑一个函数类:

@mixin bg($url) {
    background-image: url($url);
    @at-root(with: all) .webps & {
        background-image: url($url + '.webp');
    }
}

应用之后,效果等同于:

.testbg{
    background-image: url(.../test.png);
}
.webps .testbg{
    background-image: url(.../test.webp);
}

可以配合上面webp格式转换的第三种方法使用。

2. 自动化

可以借助一些其他工具,进行一些自动化的操作。当然这种适合项目中会有大量图片的情况。目前遇到的情况用上一种方法是比较简单方便且快速的。

关于webp的高级使用,后续有时间在进行补充。大家也可以网上搜索,应该会有不少文章介绍。

总结

总之,webp在进行较大图片的替换方案上,是可以作为一种解决选择的。不过由于它的兼容性着实还不是很好。所以想要大规模系统的使用还需继续观望并期待它之后的发展。

21 May 2019