当前位置: 首页 > news >正文

webp图片实践之路

我们会从三部分来聊聊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图片。

http://www.jsqmd.com/news/1104671/

相关文章:

  • 10余种 智慧航拍-无人机拍摄1W例高分辨率10余种道路损害图数据集 无人机道路病害检测数据集 裂缝 龟背坑洼检测
  • 2026-06-30 GitHub 热点项目精选
  • XUnity自动翻译器:打破语言壁垒的Unity游戏汉化神器
  • 遗传算法实战:N皇后问题的Python实现与调参避坑指南
  • PHP反序列化漏洞实战:从原理到RCE攻击链深度剖析
  • Platinum-MD:5分钟让复古MiniDisc设备在现代电脑上重获新生
  • Sigmoid与Softmax:激活函数核心区别解析
  • 用ChatGPT的Canvas模式半小时协作写好一篇文章
  • 为什么晶振要并联1MΩ电阻?
  • AI 编程代理的安全边界,已经从代码审计移到执行权限
  • AO3镜像站:5分钟掌握全球同人创作平台的免费访问方案
  • DownKyi终极使用指南:快速掌握B站视频批量下载技巧
  • WebLogic安全加固实战:从攻击面分析到纵深防御配置指南
  • 无电流传感器模型预测MPC串联型谐振DAB模型研究(Simulink仿真实现)
  • MC74HC165A与PIC18F2553在复杂系统简化中的应用
  • 如何5分钟掌握Zotero Reference:学术文献管理的终极效率提升指南
  • 如何彻底解决Windows显卡驱动问题:Display Driver Uninstaller完整指南
  • 如何为ADAS与智能座舱选择车规级高带宽内存?MT53E1G32D2FW-046 AUT:A的4266Mbps与-40℃~125℃宽温方案解析
  • NGA论坛终极优化指南:免费开源脚本让你的浏览效率提升300%
  • Figma到Unity导入终极指南:5分钟实现设计到游戏的完美转换
  • Python 方法绑定机制深度解析:为什么实例方法会自动绑定 `self`?
  • XUnity自动翻译器:让外语游戏瞬间变中文的终极解决方案
  • 瓶颈从未在于代码:重新审视 AI 时代的工程效能
  • 全新反铁磁存储
  • 手机号码定位技术终极指南:如何快速查询电话号码归属地
  • 淘宝、1688官方API,一键铺货、导入独立站、数据分析、AI比价
  • 高准确率AI编程工具每日3000万Token,新人白嫖7天会员
  • 专业嵌入式方案设计服务商 | NXP · ST · 瑞萨 · 瑞芯微 平台定制开发
  • 分布式工业通信框架:构建高可用协议栈的架构实践
  • 基于STM32和A89307的高功率FOC无刷电机控制方案