先检查一下你的浏览器是否支持 WebP 格式,如果支持的话,下面加载的图片上就会有小灯里(当然,这张图已经被转成 WebP 格式了),不支持的话图片上的小灯里就是透明人(显示另一张 JPEG 格式的图片)了~
(原图来自 Pixiv ID: 70919335)“你们都欺负灯里,好过分啊”
![](https://p.sda1.dev/12/8a84bedba4ee74125f7c51f9fcf8b541/kl8CakPN.jpg)
为什么要使用 WebP
WebP 是由 Google 收购 On2 Technologies 后发展出来的图片格式,以 BSD 授权条款发布。目前已经在不同厂商之间进行了尝试,如 Google、Facebook、ebay、百度、腾讯、淘宝等。
WebP 在支持有损、无损、透明图片压缩的同时,大大减少了图片的体积。据统计,WebP 无损压缩后比 PNG 图片体积减少了 26%,有损图片比同类 JPEG 图像体积减少了 25% ~ 34%。
↑懒得自己写介绍了,就直接复制粘贴好了~总之 WebP 是一种比 JPEG、PNG、GIF 都不知道高到哪里去了的新型图片格式。
以下面两张文件大小相似的,被压缩得惨不忍睹的高压图为例进行比较,一张是 19.2 KB 的 JPEG 图片(使用 mozjpeg 压缩),另一张是 19.0 KB 的 WebP 图片。
(原图来自 Pixabay)
![](https://p.sda1.dev/12/90c29d2d213f3f6b2ed26300450089da/0Ol7cele.jpg)
(如果看不到图片的话,说明你的浏览器不支持 WebP,可以点这里查看那张 WebP 图片转换为 PNG 格式后的图)
- 图片上方的天空,JPEG 图片中出现了很明显的色带,但是 WebP 图片中的色带相对来说不怎么明显。
- 图片下方的水波纹和左下角的码头是细节丰富的高频区域,JPEG 图片出现了明显的“小碎块”,但是 WebP 图片上这种现象就并不是十分明显。
- WebP 图片中的小船、码头、建筑物外墙等部分,比 JPEG 图片有更清晰的轮廓。
上面的对比中,WebP 的表现显然要优于 JPEG。适当调节压缩参数的话,将 JPEG 二压成 WebP 还能在一定程度上消除 JPEG 压缩时产生的块状噪点。
即使是使用 TinyPNG 有损压缩(256 色)过的 PNG 图片,再使用 WebP 无损压缩还能将文件大小继续降低至少 10%。至于 GIF 这种压缩率已经无法满足人民日益增长的精神文化需要(各种沙雕图)的动图格式,转换成 Animated WebP 也能进一步降低文件大小。
可以使用更小的文件大小,以更高的质量展示图片,那当然是要资瓷 WebP 格式的啦~
将网页的图片升级成 WebP
小透明一直在使用 ae01.alicdn.com
的接口作为图床(上传接口参见 GitHub 上的项目 upimg),之前尝试过直接上传 .webp
文件,但是会报错。最近才发现,只要将文件扩展名修改为 .jpg
、.png
、.gif
这些传统格式的扩展名,其实是可以上传任意类型的文件的……所以,把 WebP 图片修改扩展名为 .jpg
也是可以上传的,当然也可以在网页上正常使用,于是就有了在这里使用 WebP 图片的打算。
![](https://p.sda1.dev/12/88f2fe17dec2030c34a7311db981fb14/fsrE_nWY.png)
9102 年了,隔壁 Firefox 早就加入 WebP 格式的支持了,但是 iOS 上的唯一指定浏览器 Safari(虽然 iOS 上也有 Firefox 和 Chrome,但是 Apple 规定第三方浏览器必须使用 Safari 内核)仍然不支持 WebP(出来挨打!⊂彡☆))д`) ),另外 IE11 也是不支持的。所以使用 WebP 要考虑向前兼容,在不支持的浏览器上应该自动回退到使用 JPEG 等传统图片格式。
后端可以通过请求头中的 Accept
字段判断是否支持 WebP,如果支持的话对应的请求头一般是 Accept: image/webp, */*
,有些 CDN 服务根据这个实现了“自适应 WebP”的功能。不过因为小透明还是在使用公共图床,所以还是得手动生成传统格式和 WebP 两份图片,然后上传两次,在前端使用两个图片链接……
以下两种在前端自动切换 WebP 的方法,均参考自“把网站的图片升级到WebP格式吧”这篇文章。
使用 HTML5 中的 <picture>
标签
<picture>
<source srcset="large.jpg" media="(min-width: 800px)">
<source srcset="medium.jpg" media="(min-width: 600px)">
<img srcset="small.jpg">
</picture>
<picture>
主要用于网页的响应式设计,标签里面可以指定多个 <source>
,根据显示的页面宽度(在手机和电脑上是不同的)等参数,加载不同的图片(一般是清晰度、图片质量不同)。即使是老旧浏览器不支持 <picture>
,也可以直接显示里面的 <img>
,实现了向前兼容。
如果在 <picture>
里面加一个使用 WebP 图片的 <source>
,在最后的 <img>
中使用传统格式,这样就可以实现在支持的设备上优先使用 WebP。
<picture>
<source type="image/webp" srcset="image.webp">
<img src="image.jpg">
</picture>
不过小透明没有采用这种方式……因为在外面套一个 <picture>
标签会影响到 CSS 对标签的选择。小透明根据 document.querySelectorAll("#post-content p > img")
为正文部分的所有图片批量添加了“点击查看大图”的功能,如果使用这种方式的话,就需要修改 JS 和 CSS 中使用的选择器代码,需要对 <source>
和 <img>
两种元素各进行一次操作,比较麻烦。
使用 JS 检测 WebP 支持并替换
可以使用 JS 加载一张 1x1 的 WebP 图片,如果浏览器支持 WebP 的话就可以读取到图片的长和宽。
function checkWebp(callback) {
var img = new Image();
img.onload = function () { callback((img.width > 0) && (img.height > 0)); };
img.onerror = function () { callback(false); };
img.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
}
将 <img>
标签进行修改,同时写上 WebP 图片和传统格式图片的地址,然后根据检测结果决定使用哪个地址作为 src
属性的值。由于在 JS 中加载图片是异步操作(虽然从 Data URL 中加载几乎是“瞬间”完成,但加载过程本身一定是异步的),因此这个操作需要使用回调函数实现。
Markdown 的插入图片语法 ![](image.jpg)
转换出来的是一般的 <img src="image.jpg">
,因此在写博客的时候使用这种方法的话,每次插入图片时需要直接手写修改过的 HTML 代码。
这种方式的好处是除了修改 <img>
标签内的属性和添加一段 JS 代码,不需要再修改别的东西了,也是小透明目前选择的方式~用类似的方法,还可以处理 CSS 的 background-image
使用的背景图。
<!-- 一般的img标签 -->
<img class="..." src="image.jpg" alt="...">
<!-- 为了使用JS替换WebP图片而使用的标签 -->
<!-- 如果直接将传统格式图片写进src的话一打开网页就会开始加载,切换src后又会加载WebP图片,等于重新加载了两张图片 -->
<img class="..." data-src="image.jpg" data-src-webp="image.webp" alt="...">
// 如果img标签存在WebP图片的地址,就使用它进行替换,否则使用传统格式的图片的地址
// 不影响一般的img标签
function showImage(useWebp) {
var imgs = [].slice.call(document.querySelectorAll('img'));
imgs.forEach(function (e) {
if (useWebp && e.getAttribute('data-src-webp')) {
e.src = e.getAttribute('data-src-webp');
} else if (e.getAttribute('data-src')) {
e.src = e.getAttribute('data-src');
}
});
}
checkWebp(showImage);
接下来会把之前的文章的图片逐渐添加 WebP 图片的适配(已完成!),不过封面图因为是用 CSS 的 background-image
属性设定的,所以并不能做到自动切换(;-_-)
之后的文章里所有的图片也会同时准备 JPEG/PNG/GIF 和 WebP 两种格式。虽然需要多保存一张图,工作量增加了一倍(?),不过能用上新技术想想就很开心(ノ)`ω´(ヾ)
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。不允许内容农场类网站、CSDN 用户和微信公众号转载。
本文作者:✨小透明・宸✨
本文链接:https://akarin.dev/2019/10/22/upgrade-to-webp/