做有态度的前端团队

网易FEG前端团队

小白带你探索WebP

WebP是什么鬼

WebP格式,一种新型的图片格式,其图片压缩体积大约只有JPEG的2/3,而且还能节省大量的服务器带宽资源和数据空间。

这么好的图片格式,如果能运用到实际项目中那就非常棒了。但是又碍于其兼容性问题,于是就有了这个webp fis插件的诞生,暂时叫它fis-postpackager-jpg-towebp。

WebP插件主要实现的功能

  1. jpg --> webp (目前暂时仅处理jpg图片)
  2. 替换所有jpg引用(包括样式表里的和页面上的img标签,至于js里面的就不管咯)
  3. 判断是否支持webp,然后加载对应的图片格式

插件实现过程

一、选择fis插件的类型

大概浏览了一遍fis的插开发件文档,发现fis主要是以 File 对象为中心构建编译的,每一个 File 都要经历编译、打包、发布三个阶段。

既然是生成新的webp图,所以应该是fis打包阶段(postpackager)完成的,所以才会有fis-postpackager-jpg-towebp。

二、生成webp

通过imageminimageminWebp两个npm包来生成webp图

    var Imagemin = require('imagemin');
    var imageminWebp = require('imagemin-webp');
     
    new Imagemin()
        .src('images/*.{jpg}')
        .dest('build/images')  //文件夹
        .use(imageminWebp({quality: 50}))  //压缩质量
        .run(function (err, files){
            //成功生成webp   
        });
    

然后,为了保证生成的webp图是跟原来的jpg的路径和名字是一样的(方便以后的jpg替换成webp),所以做了以下处理:

基本思路

  1. 原来的jpg图的路径,可以通过file对象获取( file.subdirname + file.basename )

  2. 新的web图只要把.jpg替换成.webp

  3. 然后再通过file.getHash()判断该图片文件是否带有md5值来生成与打包后jpg的名字一致

最后的实现代码如下:


    var environment = process.argv[3];//根据命令行参数来获取当前的打包环境(release or dist);
    var origin_img_folder = file.subdirname.substring(1,file.subdirname.length); //原来jpg的文件夹路径
    var new_img_folder = (environment+file.subdirname..replace("/src",""); //新文件夹
   
    new Imagemin()
        .src(origin_img_folder+'/'+file.basename)   
        .dest(new_img_folder)                       //新文件夹
        .use(imageminWebp({quality: 50}))           
        .run(function (err, files){
            
            //重命名当前webp文件
            var newpath;
            if(file.useHash){
                newpath = files[0].path.replace(file.filename,file.filename+'_'+file.getHash()); //生成带md5的webp图片路径
                fs.rename(files[0].path, newpath,function(){});
            }

    });
        

三、替换css文件里所有jpg引用,并生成一份新的css文件

遍历所有css文件,包括合并后的,正则匹配后替换,代码如下:


    function replaceAllJPG(css_content, file, subpath){
        var file_url,
            reg = /\/+(\w*)(.jpg)/; //匹配规则
    
        css_content = css_content.replace(reg, function (m, $1) {
            if($1){
                return m.replace('.jpg','.webp');
            }
            return m;
        });
        
        //生成新的css文件
        if(!fis.util.isDir(subpath)){
            fis.util.mkdir(subpath); 
        }
        if(file.useHash){
            file_url = subpath+"/"+file.filename+'_'+file.getHash()+"_webp.css";
        }else{
            file_ur, = subpath+"/"+file.filename+"_webp.css";
        }
        fs.writeFile(file_url, css_content, function(err) {
            if(err) {
                //return console.log(err);
            }
        });
    }
        

四、处理html文件

基本思路

  1. 匹配处理link, img标签

  2. 自定义两个属性data-webpOriginal和data-webpNew分别存放原来的和新建的样式表(图片)地址

主要就是用正则表达式去匹配处理,代码就不贴了。有兴趣的童鞋可以自己看源码,也欢迎提出更好的正则表达式。

真心觉得学好正则好重要啊(╯‵□′)╯︵┻━┻

五、判断是否支持webp

写到这里突然饿了,就这样先吧,大家敬请期待下篇吧。

请输入图片描述

手机阅读请扫描下方二维码:

添加新评论

ali-40.gifali-41.gifali-42.gifali-43.gifali-44.gifali-45.gifali-46.gifali-47.gifali-48.gifali-49.gifali-50.gifali-51.gifali-52.gifali-53.gifali-54.gifali-55.gifali-56.gifali-57.gifali-58.gifali-59.gifali-60.gifali-61.gif