方案价值
CDN 厂商无关
节省 CDN 处理费用(相对其他方案)
应用场景
一般情况下,postcss 处理插件默认引入。
覆盖用户图片上传入口,将用户上传的图片转换为 webp + 原格式,在兼容的设备上均以 webp 呈现。如果原图被 tinypng 压缩过,且压缩率良好,可以不使用 webp 进行处理。
如何使用:
图片标签
使用组件库提供的图片组件
注意在升级组件到2.3.x
此时对于modal有些许调整,请仔细查看升级文档 https://gitlab.yc345.tv/frontend/onion-ui/-/releases 。
自动引入 import '@guanghe-pub/onion-ui/lib/base-css.css'
ui包升级
"@guanghe-pub/onion-ui": "2.3.4"babel包升级
"@guanghe-pub/babel-plugin-import-onion-ui": "1.1.4"import { OIImgLoad } from "@guanghe-pub/onion-ui";
<OIImgLoad
webp="custom"
src="https://fp.yangcong345.com/vip/img/1.d7061977.png"
alt="洋葱学园"/>
// 在支持webp的浏览器中,加载的图片地址会变为
// https://fp.yangcong345.com/vip/img/1.d7061977.webp
背景图片css
step1 : 项目配置postcss.config插件
plugins: {
'@guanghe-pub/postcss-plugin-auto-webp': {
exclude: ['node_modules'],
},
},step2: html中写入一段代码
<script>
const isSupport =
!![].map &&
document
.createElement('canvas')
.toDataURL('image/webp')
.indexOf('data:image/webp') === 0
console.log('🚗🚗🚗🚗🚗 检测当前是否支持webp', isSupport)
if (!isSupport) {
document.body.setAttribute('no-webp', 'true')
}
</script>step3: 上传图片的时候选择支持webp类型
然后代码中正常使用普通格式
.att1 {
background: url('xxxxxx.b37954ea8eccc976d71dedb0__w.jpeg')
no-repeat 100% / 100%;
}上传入口
使用新版支持webp的上传组件 升级uplaod包,默认支持webp
https://npm.yc345.tv/-/web/detail/@guanghe-pub/yc-upload
方案实现:
前置实现 - Upload Hook
前端:
在上传图片接口表单里,增加接收两个参数(可选):
message Request{
bool webp = 1; // 是否开启转换为 webp,默认为 true
bool convertName = 2 ; // 是否转换文件名,默认为 true
}后端:
根据请求表单参数,后端处理在上传图片时,分别进行不同处理。
webp 为 true 或为空时:
同时上传源文件 + 根据源文件类型,按约定命名的转换+压缩后的 webp(可选)。:
接口返回增加 convert 字段,返回转换后的 webp 图片的地址。
webp 为 false 时:
按以前操作处理,并且屏蔽 convertName 参数的值。
convertName 为 true 或为空时:
将源文件名转换为 xxx__w.{png/jpeg},意为将源文件标记为支持 webp,方便图片组件进行处理。
convertName 为 false 时:
不做任何转换文件名处理
边界情况:由于 webp 可能存在转换失败的情况,建议考虑先处理 webp 的转换,而不是先上传源文件,如果 webp 转换失败,则上传源文件名,不加 __w 后缀。
返回结果例: webp true convertName true
{
"code": 200,
"data": {
"key": "https://fp.yangcong345.com/middle/1.0.0/shareCard31__w.png",
"convert": "https://fp.yangcong345.com/middle/1.0.0/shareCard31__p.webp"
}
}例:
foobar.png => foobar__w.png + foobar__p.webp foobar.jpg => foobar__w.jpg + foobar__j.webp foobar.jpeg => foobar__w.jpeg + foobar__je.webp
源文件:
"__w" 指该图片支持 webp,前端使用到该图的地方,可以安全进行 webp 升级/回退。
转换后:
“p” 指支持 alpha 通道的 PNG 格式,即支持透明通道的 PNG 格式。 “j” 指 JPG 格式。 “je” 指 JPEG 格式。
TODO & Check List:
指定转换参数
quality=80 # ❓ 图片质量是否指定为 80 mode=RGB # ❓ 色彩空间是否指定为 RGB,需要跟设计同学的图片标准沟通 lossless=false # ❓ 是否开启无损压缩,与图片质量互斥libwebp 图像质量与压缩选项
-q<float>默认值:75 中文名:图像质量(0 至 100)-m<int>默认值:4 中文名:压缩方法(0 至 6,数值越大压缩越好但速度越慢)-lossless默认值:无 中文名:无损压缩-preset<default|photo|picture|drawing|icon|text>默认值:default 中文名:预设设置
转换结果是否包含元数据?
<img/> 标签图片的处理
基于 Onion-ui ImgLoad 实现通用 <AutoWebp /> 组件。
实现方案和实现原理:
利用 Picture 的回退特性,在浏览器层级自动判断加载何种类型的图片。
例:
<AutoWebp alt="foobar" src="https://fp.yangcong345.com/middle/1.0.0/auto-webp-logo__p.webp" click={foobar} />转换结果等同于:
<picture> <source srcset="https://fp.yangcong345.com/middle/1.0.0/auto-webp-logo__p.webp" type="image/webp"> <img alt="Vue logo" width="128" height="128" src="https://fp.yangcong345.com/middle/1.0.0/auto-webp-logo.png" onClick="foobar"> </picture>透传所有原生事件到 picture > img 标签上,由于 picture 不会影响布局,所以该 picture > img 表现形式等同于原生 img 标签。
考察下一步废弃 <= Android 5.x 后,是否可以使用原生 Web Component 实现该组件(跨框架、体积小、0️⃣运行时)。
CSS url image 图片的处理
使用 postcss 插件: __guanghe-pub/postcss-plugin-auto-webp 是一个转化 background-image: url(xxx.(png|jpeg...)) 属性到 webp 的插件,支持在不支持的浏览器下,自动回退到原始格式。
实现方案和实现原理:
在 Dom 文档加载完成后(document.ready),对该浏览器是否支持 webp 进行判断,如果支持 webp,则给
body一个 attr:webp,即:<body no-webp/>postcss 将 scss/less 中所有含有
url(xxx.{png/jpg...})的 class 生成一个 [no-webp] [.selector] 的副本,仅在#app webp属性生效时加载 webp 图片,其他时候还是加载原图。 例:.test{ background: url(bg__p.webp); background-image: url(bg-img__j.webp); mask-image: url(mask__je.webp); border-image: url(border-image.png); // ... .foobar{ border-image: url(foobar-border-image__j.webp); // ... } }转换结果:
.test { // <-- 不做任何处理 background: url(bg__p.webp); background-image: url(bg-img__j.webp); mask-image: url(mask__je.webp); border-image: url(border-image.png); } .test .foobar{ // <-- 不做任何处理 border-image: url(foobar-border-image__j.webp); } [no-webp] .test{ // <-- ♻️ 添加不支持 webp 时的回退 background: url(bg.png); background-image: url(bg-img.jpg); mask-image: url(mask.jpeg); } [no-webp] .test .foobar{ // <-- ♻️ 添加不支持 webp 时的回退 border-image: url(foobar-border-image__p.webp); // <-- 🌲 包含子层级的转换结果 }
方案优势
拓展性:未来放弃不兼容 webp 的设备时,我们只需要将 @guanghe-pub/auto-webp-postcss-plugin 插件做一个废弃。
对动态加载的图片友好:利用 AutoWebp 组件加载 img 标签时,
兼容性好
其他
文件格式信息表
压缩比例是测试采用 convert.py 从 https://random.imagecdn.app 随机取样10 张 png 和 10 张 jpg 进行转换后统计得出结果。
action
使用方的角度应该在什么场景下如何使用
为什么cdn上加入尺寸限制的后缀后webp反而比jpeg更高