我们会从三部分来聊聊webp这个话题。

  1. 什么是webp,它有什么用?
  2. 使用webp的常规方法以及优劣。
  3. 我们是如何用上webp的。

PS:如果是对webp有一定了解的朋友,建议直接看第三部分。因为是讲我们的实践之路,所以第三部分会多讲一些。

一、什么是webp,它有什么用?

webp是谷歌推出的一种图片格式,它的优点就是同等画面质量下,体积比jpg、png这些少了25%以上。

大家都知道移动互联网时代,页面大小和用户留存息息相关,更快的加载页面才能让更多用户关注到你的内容,而图片一直都是页面体积的大头,拿我们的活动页面来说,图片占据了80%以上的页面大小。所以使用webp的话,可以瞬间让页面大小下降1/4,不得不说是一个极具性价比的优化点。

当然,它也不是没有缺点,浏览器对于webp的解码速度相对于jpg来说会慢一些,不过这和体积减小带来的性能提升,可以忽略不计了。

那么既然webp这么好,为什么没有大范围使用呢?归根结底还是webp是谷歌推出的,目前主流浏览器只有chrome和安卓支持。不过IOS也快支持了,期待ing^ ^。在caniuse上可以查到webp目前的兼容性。

二、使用webp的常规方法以及它们的优劣

首先,我们需要一个工具把图片转成webp格式,这里就使用google的官方工具即可,链接。

这个装好之后,你的控制台就有了一个cwebp命令。运行cwebp -h,成功显示帮助信息就表示安装好了。

通过这个工具就可以生成webp图片了,有了webp图片之后,之后便是如何使用了,常见有两种方案。

方案一:服务器端处理

这是最最最省心的方法了,支持webp图片的浏览器在向服务器发送请求时,会在请求头Accept中带上image/webp。然后服务器就可以根据是否含有这个头信息来决定是否返回webp图片了。

这个方法只需要在web服务器那里做一些操作即可,十分简单方便。

不过这个方案缺点也很明显,首先通过请求头检测,某些设备可能不太准。其次,现在图片等静态资源都会放到CDN服务器上,那么在这个层面加上判断webp的逻辑就有点麻烦了。

方案二:前端检测是否支持webp然后再请求相应格式的图片

这个方法好处是十分稳妥,通过特性检查可以知道用户的浏览器是否支持webp,坏处就是需要在业务代码中加入检测webp的逻辑。

通常做法是在页面加载前先执行一段webp的检测,得出浏览器是否支持webp格式,把结果存入cookie中,在加载图片时,如果是懒加载的图片,那么根据是否支持webp来处理图片路径就好,如果不是懒加载的图片,可以在后端渲染模板时,根据我们设置好的是否支持webp的cookie来判断。

目前这些都是针对页面通过img标签引入图片时兼容webp的方式。如果是css中引入的图片,方案一般就是构建两套css,然后在后端模板中根据cookie判断使用哪一套,或是在css中通过选择器覆盖,比如对于支持webp的浏览器,我们在html根节点上加上webps的类名,然后针对引入的图片,通过这个类名做选择器优先级覆盖,具体的我们在第三部分看着代码细说。

三、我们是如何用上webp的

重点来了,下面来说说我们对webp的实战。

首先说说我们这边现状吧,我们的图片有两种存放方式。对于一些动态图片,比如商品图,这些是存放在我们的图片服务器上,这个服务器支持webp格式,只需要在图片路径后面加上参数t=5即可得到webp格式的图片。

对于css引入的背景图,我们存放在某个CDN上,这部分就麻烦了,不支持生成webp图片,所以只能自己传一份相应的webp图片上去。

而且由于各种原因和限制,我们无法采用上述说的服务器端处理方案,所以只能采用前端代码处理的方式。我想有些公司没使用webp可能也是这些原因,因为纯前端处理确实挺绕的。

结合我们的业务情况,因为是运营活动页,背景图和商品图基本各占一半,甚至背景图更多,所以我们需要把css引入的图片和img标签引入的图片都做webp兼容T T。

针对img标签引入的图片,由于我们的图片服务器支持webp,而且我们的商品图大多是懒加载,那么就简单了,直接修改我们的懒加载插件就可以实现,在替换真实图片路径的时候判断一下是否支持webp,然后替换相应的路径就可以。

针对css引入的图片,我们采取的方案是利用css的优先级覆盖,比如说如果浏览器支持webp,那么我们给html根节点上加上webps的类名。这样比如我们写

span{background-image:url(a.jpg)}

的时候,再写上

.webps span{background-image:url(a.jpg.webp)}

这样,支持webp格式的设备就会自动加载webp的图片了。

当然这里你肯定会有两个疑问

一是每次写代码的时候加上.webps再写一遍工作量也太大了。

二是每张图对应的webp图片是哪里来的?需要自己生成吗?

针对这两个问题,我们找到了相应的解决方法,对于问题一我们使用css预处理器做到了生成对应的webp的代码。

问题二我们使用nodejs写了一个脚本来监控图片文件夹,当图片增加、修改、删除时,它便会生成或删除对应的webp图片。

说了这么多,我们一起来看一看代码实现吧。

首先,我们需要在页面最开始的部分加入一段webp的检查代码。这段代码的作用就是检查当前浏览器是否支持webp,如果支持,那么给html根节点加上webps的类名,以供css使用。并且在cookie中记录一个名为webps,值为A的cookie,为期一年。这样,之后就可以在css中使用webp类名做兼容处理,img标签引入的图片也可以通过cookie得知浏览器是否支持webp,然后做相应处理,后端也可以通过cookie得知设备对webp的支持情况来做一些差别渲染。

这段代码如下,需要注意的是这段代码要在引入css前就加载,代码的含义可以直接看注释。

;(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)); 

然后我们处理img标签引入的图片,因为我们的图片服务器支持webp,且用img引入的图片都是通过懒加载来载入的,所以这部分我们处理起来比较简单,在懒加载替换真实路径的时候,判断cookie中是否存在webps=A这个cookie来决定加载的图片的url。

当然,如果你们不是懒加载的引入的图片,那么可以在后端渲染的时候,通过我们写入的cookie,来判断是否使用webp图片,也很方便。这部分代码比较简单,就不贴出来了。

然后是css中引入的图片了,由于css不支持逻辑,我们现在能利用的就是html根节点的.webps的类名了。我们在SCSS中使用了这个mixin来加载图片。代码作用可以看下注释。

/*
通过这个函数来引入图片,例如:
#wrapper{ @include bg('../img/sample.jpg') }
这段代码经过编译后便会生成如下两句代码
#wrapper{ background-image:url('../img/sample.jpg'); }
.webp #wrapper{ background-image:url('../img/sample.jpg.webp'); }
*/
@mixin bg($url) {
background-image: url($url);
@at-root(with: all) .webps & {
background-image: url($url + '.webp');
}
} 

如果用的是less,可以通过下面这段代码来实现同样的功能。

.mixin(@url) {
background-image: url(@url);
.webps & {
background-image: url('@{url}.webp');
}
} 

最后就是如何生成webp图片了。对于css引入的图片,由于是放在CDN上,我们需要自己生成对应的webp图片。

如何做到开发的时候自动配套生成webp图片呢,开始我们想的是给我们的构建工具写个插件来实现编译时候生成webp图片,然而我们发现由于各个项目使用的构建工具可能不一样,比如fis3、webpack还有我们自己开发构建工具的,太多了,针对每一个开发成本太高。所以我们决定用nodejs写个小脚本,作用就是监控我们的图片文件夹,随时生成配套的webp图片,当图片有增加、修改、删除时,它会相应的增加、修改、删除对应的webp图片。

工具代码如下。默认监听images文件夹,npm install 安装依赖之后,直接node webp-monitor.js既可。当然,前提是你按照好了第二部分所说的谷歌官方的webp生成工具,或者简单的说你的终端需要有cwebp这个命令才行。

/*
webp图片生成 运行:npm install && npm start 程序依赖谷歌官方webp转换工具cwebp
mac下安装 brew install webp
windows下可以去google官方下载 安装完成后运行cwebp -h 如果显示了使用帮助则表示安装成功
*/ const process = require('child_process');
const fs = require('fs');
const chokidar = require('chokidar'); const log = console.log.bind(console);
const ignoreFiles = /(^\..+)|(.+[\/\\]\..+)|(.+?\.webp$)/; // 忽略文件.开头和.webp结尾的 let quality = 75; // webp图片质量,默认75
let imgDir = 'images'; // 默认图片文件夹 // 得到对应的webp格式的文件名,默认为文件名后加上.webp
function getWebpImgName(path) {
return `${path}.webp`;
} // 得到shell命令
function getShellCmd(path) {
return `cwebp -q ${quality} ${path} -o ${getWebpImgName(path)}`;
} // 监控文件夹
var watcher = chokidar.watch(imgDir, {
ignored: path => {
return ignoreFiles.test(path);
},
persistent: true // 保持监听状态
}); // 监听增加,修改,删除文件的事件
watcher.on('all', (event, path) => {
switch (event) {
case 'add':
case 'change':
generateWebpImg(path, (status) => {
log('生成图片' + getWebpImgName(path) + status);
});
break;
case 'unlink':
deleteWebpImg(getWebpImgName(path), (status) => {
log('删除图片' + getWebpImgName(path) + status);
});
break;
default:
break;
}
}); log('biubiubiu~~~ 监控已经启动'); function generateWebpImg(path, cb) {
process.exec(getShellCmd(path), err => {
if (err !== null) {
cb('失败');
log('请先运行cwebp -h命令检查cwebp是否安装ok。')
log(err);
} else {
cb('成功');
}
});
} function deleteWebpImg(path, cb) {
fs.unlink(path, (err) => {
if (err) {
cb('失败');
log(err)
} else {
cb('成功');
};
});
} 

至此,我们便实现了在项目中使用webp图片。



WebP 图片实践之路的更多相关文章

  1. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  2. webp图片实践之路(转载)

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  3. 【原】webp图片牛刀小试

    其实今年很早就有接触到webp图片的概念,只是一直没怎么弄.今天在一个小项目中小用了一番.总结总结 采用 what,why,how的方式来总结 what? 什么是webp图片? 维基百科:       ...

  4. webp图片技术调研最终结论(完全真实数据可自行分析)

    关于webp图片格式调研及测试 资料收集 什么是 WebP? WebP(发音 weppy),是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式 VP8.根据 Google 的测试,无损压缩 ...

  5. 如何让Ubuntu系统支持WebP图片格式

    本文主要向大家介绍如何让 Ubuntu 系统支持查看 WebP 图片格式,以及如何将 WebP 转为 JPEG 或 PNG 图片格式的方法. 什么是WebP图片 Google开发并推出 WebP 图片 ...

  6. 网站页面优化必然趋势—WebP 图片!

    本文梗概:众所周知,浏览器可以通过 HTTP 请求的 Accpet 属性 来指定接收的内容类型.依靠这个技术,可以在不修改任何 HTML/CSS 或者图片的情况下,向浏览器提供优化的图片,从而降低带宽 ...

  7. 提升网站用户体验—WebP 图片的高效使用

    一.WebP 的由来 现代图像压缩技术对我们的生活方式影响很大.数码相机能将上千张高质量图片存储到一张内存卡里.智能手机可以与邻近设备快速分享高分辨率的图片.网站与手机等移动设备能快速展示各种富媒体. ...

  8. webp图片详解

    WebP(发音 weppy),是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式 VP8.根据 Google 的测试,无损压缩后的 WebP 比 PNG 文件少了 45% 的文件大小,即使 ...

  9. 《程序设计语言——实践之路》【PDF】下载

    程序设计语言--实践之路>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382240 内容简介 本书在美国大学已有使用了十余年,目前被欧 ...

随机推荐

  1. Java学习笔记5(类的入门以及ArrayList)

    1.类的概念:将现实生活中的事物抽象成了代码(类),我们可以使用自定义的数组类型(类)来描述现实生活中的事物. 2.分析:用一部手机来分析,手机可以打电话,上网,听音乐,这些就是方法,手机有型号,颜色 ...

  2. Mac appium.dmg. Xcode Command Line Tools

    You need to install the command line tools as marked in your message: ✖ Xcode Command Line Tools are ...

  3. Updates were rejected because the remote contains work that you do(git报错解决方案)

    Updates were rejected because the remote contains work that you do(git报错解决方案) 今天向GitHub远程仓库提交本地项目文件时 ...

  4. Linux进程关系(转载)

    Linux的进程相互之间有一定的关系.比如说,在Linux进程基础中,我们看到,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构.我们在这里讲解进程组和会话,以便以更加丰富的方式了 ...

  5. kylin客户端(python编写)不能按照预期的segment进行rebuild

    kylin_client_tool 提供了对cube进行BUILD,REBUILD,MERGE功能,其中REBUILD却不能达到预期的效果按照指定的segment执行. 场景: 当我在kylin we ...

  6. 使用docker+jenkins构建nodejs前端项目

    前文使用Docker搭建Jenkins+Docker持续集成环境我们已经搭建了基于docker+jenkins的持续集成环境,并构建了基于maven的项目.这一节,我们继续扩展功能,增加对Nodejs ...

  7. echarts3 中 热力图的属性大全

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  8. Linux centos7系统下svn的安装与配置

    一.安装svn # yum -y install svn 二.查看svn版本信息 # svnserve --version 三.搭建svn版本库(假设项目名称为project) 1.首先创建版本库目录 ...

  9. JavaScript语法详解:JS简介&变量

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. JavaScript简介 Web前端有三层: HTML:从语义的角度,描 ...

  10. 记一次lvs-tunnel模式的故障分析(7)

    一.测试环境   类型 IP 负载均衡器 eth0:10.20.73.20 VIP eth0:0 10.20.73.29 后端真实机 10.0.0.7(web01).10.0.0.9(web02)   ...