EdgeOne边缘函数实现全站图片转AVIF
AVIF 相较于传统图片格式(如 JPEG、PNG)具有更高的压缩效率,文件体积更小,支持 HDR 和透明通道,同时画质更佳。与 WebP 相比,AVIF 的压缩率高 10%-30%,在低码率下画质更出色。本文老白博客基于腾讯云EdgeOne自带的边缘函数,实现全站图片转AVIF,并对不支持的浏览器采用对应的格式显示。
1.avif与webp对比
avif格式与webp格式图片的对比
- 压缩效率:与 WebP 和其他图像格式相比,AVIF 提供了卓越的压缩效率。它可以实现更高水平的压缩,同时保持出色的图像质量。
- 图像质量:AVIF 支持广泛的色彩空间,包括 HDR(高动态范围)、宽色域和深色。它还支持无损和有损压缩,允许多种图像质量选项。
广泛的浏览器支持
虽然 AVIF 仍然相对较新,但近年来它获得了重要的浏览器支持。Google Chrome,Mozilla Firefox和Microsoft Edge等主要浏览器增加了对AVIF的支持
参考网页:https://caniuse.com/?search=avif
2.EdgeOne边缘函数转avif
点击函数管理,选择新建函数
任意选择一个,比如图片处理,然后点击下一步
全选删除原来的,将下面的代码①,或者代码②粘贴即可
边缘函数代码①
全选删除已有的函数代码,然后添加下方的代码,点击部署。
// 此处规定浏览器使用图片格式-https://www.xcbtmw.com/31278.html
const broswerFormat = {
Chrome: 'avif',
Opera: 'webp',
Firefox: 'avif',
Safari: 'avif',
Edge: 'avif',
IE: 'jxr',
QQBrowser: 'webp' // QQ 浏览器使用 WebP 格式
};
addEventListener('fetch', event => {
// 当函数代码抛出未处理的异常时,边缘函数会将此请求转发回源站
event.passThroughOnException();
event.respondWith(handleEvent(event));
});
async function handleEvent(event) {
const { request } = event;
const userAgent = request.headers.get('user-agent');
const browser = getBroswer(userAgent);
const format = broswerFormat[browser] || 'webp';
// 始终转换图片格式,根据浏览器设置的格式进行处理
const response = await fetch(request, {
eo: {
image: {
format
}
}
});
// 设置响应头并返回转换后的图片
const modifiedResponse = new Response(response.body, response);
modifiedResponse.headers.set('x-ef-format', format);
return modifiedResponse;
}
function getBroswer(userAgent) {
if (/QQBrowser/i.test(userAgent)) {
return 'QQBrowser'; // 新增对 QQ 浏览器的判断
}
if (/Edg/i.test(userAgent)) {
return 'Edge';
}
if (/Trident/i.test(userAgent)) {
return 'IE';
}
if (/Firefox/i.test(userAgent)) {
return 'Firefox';
}
if (/Chrome/i.test(userAgent)) {
return 'Chrome';
}
if (/Opera|OPR/i.test(userAgent)) {
return 'Opera';
}
if (/Safari/i.test(userAgent)) {
return 'Safari';
}
}
边缘函数代码②
修改说明:
- 增加了一个大小判断,如果转avif后,图片体积增大,则强制转化为webp
// 浏览器使用图片格式-https://www.xcbtmw.com/31278.html
const broswerFormat = {
Chrome: 'avif',
Opera: 'webp',
Firefox: 'avif',
Safari: 'avif',
Edge: 'avif',
IE: 'jxr',
QQBrowser: 'webp' // QQ 浏览器使用 WebP 格式
};
addEventListener('fetch', event => {
// 当函数代码抛出未处理的异常时,边缘函数会将此请求转发回源站
event.passThroughOnException();
event.respondWith(handleEvent(event));
});
async function handleEvent(event) {
const { request } = event;
const userAgent = request.headers.get('user-agent');
const browser = getBroswer(userAgent);
let format = broswerFormat[browser] || 'webp'; // 默认格式为 WebP
// 获取原始图片的响应
const originalResponse = await fetch(request);
const originalBuffer = await originalResponse.arrayBuffer();
const originalSize = originalBuffer.byteLength;
// 尝试转换为目标格式(初始为 AVIF 或其他指定格式)
const transformedResponse = await fetch(request, {
eo: {
image: {
format
}
}
});
const transformedBuffer = await transformedResponse.arrayBuffer();
const transformedSize = transformedBuffer.byteLength;
// 如果转换为 AVIF 后体积增大,则强制转换为 WebP
if (format === 'avif' && transformedSize > originalSize) {
format = 'webp';
const webpResponse = await fetch(request, {
eo: {
image: {
format
}
}
});
const response = new Response(webpResponse.body, webpResponse);
response.headers.set('x-ef-format', format);
return response;
}
// 设置响应头并返回转换后的图片
const response = new Response(transformedBuffer, transformedResponse);
response.headers.set('x-ef-format', format);
return response;
}
function getBroswer(userAgent) {
if (/QQBrowser/i.test(userAgent)) {
return 'QQBrowser'; // 新增对 QQ 浏览器的判断
}
if (/Edg/i.test(userAgent)) {
return 'Edge';
}
if (/Trident/i.test(userAgent)) {
return 'IE';
}
if (/Firefox/i.test(userAgent)) {
return 'Firefox';
}
if (/Chrome/i.test(userAgent)) {
return 'Chrome';
}
if (/Opera|OPR/i.test(userAgent)) {
return 'Opera';
}
if (/Safari/i.test(userAgent)) {
return 'Safari';
}
}
3.EdgeOne触发规则
选择and,然后host填写你添加的网站域名,然后这里还可以选择你想要的图片格式
3.1 效果演示
测试用原始图片请求 URL 为:https://www.xcbtmw.com/wp-content/uploads/2024/11/sitelogo.webp
访问后查看响应头如:content-type:image/avif
4.说明
这种转换方式未改变原始图片格式,未改变数据库结构
如果想要永久性转换,参考:
更多有关腾讯云EdgeOne边缘函数使用可见文末标签。
按F12打开控制台,搜索avif,一个avif图片都没有
……😤😤😤,它改的是图片跳转地址,没有修改数据库,你要看响应标头。另外,我的网站给关闭了,因为我用了几个图片处理的边缘函数,好像有点冲突,我得去问问客服执行的优先级。