腾讯EdgeOne产品测评体验—边缘函数实现自适应图片格式转换

前言

一般的论坛站点中都会存储大量的图片,图片文件的格式需要根据浏览器的类型来进行适配,返回浏览器可兼容的图片格式,同时最大程度上压缩图片的大小,来节省流量。例如:

● 当用户使用 Chrome、Opera、Firefox、Edge 浏览器访问图片时,响应 webp 格式图片。

● 用户使用 Safari 浏览器访问图片时,响应 jp2 格式图片。

● 用户使用 IE 浏览器访问图片时,响应 jxr 格式图片。

● 通过其他浏览器访问图片时,统一响应 webp 格式图片。

实现论坛站点自适应图片格式转换有多种方法,本文分别以浏览器端JavaScript检测替换和EdgeOne Worker边缘函数两种方法为例,做一个差异化对比。

JavaScript检测替换

逻辑

通过浏览器端JavaScript检测替换图片格式主要有以下两个步骤

1. 检测WebP支持:创建一个新的Image对象。

a. 尝试加载一个已知的小尺寸WebP图片(通常使用Base64编码的字符串)。

b. 监听onload和onerror事件。如果onload事件触发,说明浏览器能够成功加载WebP图片,因此支持WebP格式。如果onerror事件触发,则说明浏览器不支持WebP格式。

2. 替换图片地址:根据上一步的检测结果,决定使用WebP格式的图片还是传统的JPEG或PNG格式的图片。

a. 更改图片元素的src属性,指向相应格式的图片地址。

代码

代码语言:javascript
复制
function isWebPSupported() {  
    return new Promise((resolve) => {  
        const img = new Image();  
        img.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA'; // WebP格式的Base64编码图片  
        img.onload = () => resolve(true);  
        img.onerror = () => resolve(false);  
    });  
}

function replaceImage(imgElement, webpSrc, fallbackSrc) {
isWebPSupported().then((supported) => {
if (supported) {
imgElement.src = webpSrc;
} else {
imgElement.src = fallbackSrc;
}
}).catch((error) => {
console.error('Error detecting WebP support:', error);
// 如果检测WebP支持时出现错误,可以选择回退到fallbackSrc或执行其他逻辑
imgElement.src = fallbackSrc;
});
}

// 使用方法
const imgElement = document.getElementById('myImage');
const webpSrc = 'path/to/your/webp/image.webp';
const fallbackSrc = 'path/to/your/fallback/image.jpg';
replaceImage(imgElement, webpSrc, fallbackSrc);

在这个实现中,isWebPSupported函数返回一个Promise,当WebP支持性检测完成时,Promise会被解析为true(支持)或false(不支持)。replaceImage函数则根据这个Promise的解析结果来动态地替换图片的src。

EdgeOne Worker边缘函数

通过使用EdgeOne Worker的边缘函数灵活的图片处理能力,帮助我在不修改原始客户端请求 URL 的情况下,由 EdgeOne 的边缘函数来自动触发图片格式转换,自适应根据客户端的 User-Agent 信息来响应指定的图片格式。从而在不需要更改业务逻辑的情况下,自适应地提供最佳格式的图片,减少流量消耗。

购买EdgeOne Worker

首先需要进入EdgeOne Worker 产品页

根据自己的需求选择下面的配置,这里我选用399的基础版。

够买之后点击立即使用即可进入操控台

添加站点

进入控制台后在服务总览位置点击添加站点

然后输入域名,这里也有无域名输入可以选择,然后点击下一步。

然后绑定刚刚购买过的套餐,同意协议后下一步。

在选择加速区域时,根据个人或企业的实际需求进行考量。如果希望网站能够覆盖全球用户,那么选择全球可用区(即境内+境外)。注意,如果使用的是已备案域名,并不建议单纯选择纯境外区域,因为EO的部分境外节点在国内可能受到访问限制,这可能会影响到网站在国内的访问速度和稳定性。因此,为了确保网站在全球范围内的顺畅访问,建议综合考虑并选择境内+境外的加速区域。

EO提供了两种接入方式:CNAME接入和NS接入。CNAME接入是一种较为常见的接入方式,而NS接入则类似于CF,意味着将域名的DNS解析完全托管给EO。除非处理的是全新的域名,否则不推荐使用NS接入方式。在本文章中,我主要介绍CNAME接入方法。

最后是验证归属权,这里也可以点暂时跳过验证,比较简单就不一一赘述。

实现图片格式转换

登录 边缘安全加速平台 EO 控制台,通过站点列表,选择需配置的站点,进入站点管理二级菜单。

在左侧导航栏中,单击边缘函数 > 函数管理。

在新建函数这里会有许多模版可以快速创建,这里我选图片处理,然后下一步。

函数名和描述可以自己随便填一下,下面的代码已经给出了一个示例,可以根据需求进行修改。

编辑完成函数后,单击创建函数并部署,函数部署后,可直接单击新增触发规则,前往配置该函数的触发规则。

在函数触发规则中,配置该函数的触发条件,根据当前的场景需求,可以配置两条触发条件,这里以 And 逻辑触发。

该请求 URL Path 等于 /image/*。

当请求 URL 符合以上条件时,将触发以上的边缘函数,对图片进行自动处理。

单击保存触发规则即可生效。

接下来验证一下边缘函数是否生效,可以通过浏览器进行测试。

在不同的浏览器地址栏中打开控制台后,输入测试图片的地址 ,可通过响应图片的格式查看当前边缘函数是否已生效。

实现图片大小调整

EO服务器提供了强大的图片处理功能,除了转换图片格式以外还可以调整图片的大小。下面演示一下如何调整图片的大小

调整图片大小有两种方式,一种是直接在URL中添加参数,另一种通过边缘函数进行调整。

URL中拼接参数

上面是参数对应的参数值,我们只需要在原URL后面拼接eo-img.resize=xxxxxx即可

例如我希望把原图大小转换为宽度为300px,高度为200px。那么拼接后的URL就是http://www.csdn.net/foo.png?eo-img.resize=w/300/h/200。如果你不希望改变URL可以用第二种方法,通过边缘函数进行调整

边缘函数

同样的,我们先新建一个函数,创建步骤同前面一样,这里就不再创建了。

然后点击函数名

点击编辑代码

然后将之前示例给的替换图片格式代码删掉

换成下面自己写的调整图片大小的代码

代码语言:javascript
复制
const maxSize = {
width: 800,
height: 600
};

addEventListener('fetch', event => {
event.passThroughOnException();
event.respondWith(handleEvent(event));
});

async function handleEvent(event) {
const { request } = event;
const userAgent = request.headers.get('user-agent');
const bs = getBroswer(userAgent);

// 检查是否需要对图片进行大小调整
if (!isImageRequest(request)) {
return fetch(request);
}

// 创建一个新的fetch请求,包含图片大小调整指令
const resizedResponse = await fetch(request, {
eo: {
image: {
resize: {
width: maxSize.width,
height: maxSize.height,
fit: 'contain' // 或者使用 'cover' 来裁剪图片以填充指定大小
}
}
}
});

// 设置响应头,表明图片已被调整大小
resizedResponse.headers.set('x-ef-resized', 'true');

return resizedResponse;
}

function isImageRequest(request) {
const contentType = request.headers.get('content-type');
return contentType && contentType.includes('image');
}

function getBroswer(userAgent) {
// ... (此部分与之前的代码相同,用于获取浏览器类型)
}

最后点击保存并部署,触发规则呢我们还用之前的规则,然后通过浏览器打开就可以测试。

通过直接在EO服务器上进行图片处理、缓存和响应,业务源站仅需存储原始图像,从而显著降低了图片管理的成本。此外,EdgeOne边缘服务器还能够在不牺牲视觉质量的前提下对图片进行压缩,进而提升页面的加载速度并优化图片加速性能。

总结

通过这次差异化对比,我做出了以下几点总结:

在用JavaScript检测替换图片格式时需要注意的是,使用Base64编码的小尺寸WebP图片来检测支持性是一种常见做法,但这样做会增加页面的加载负担。另外,一些现代浏览器可能默认支持WebP,但出于某些原因(如用户设置、浏览器扩展等)可能禁用了WebP的支持。因此,这种方法并不能保证在所有情况下都能准确检测WebP的支持性。

而通过使用EdgeOne Worker的边缘函数就可以准确检测WebP的支持性,并且可以大大的简化过程、无需在客户端进行检测,减轻了客户端的负担、可以保证转换质量和速度,适用于大量图片的批量转换。当然也有一些缺点,比如依赖于服务提供商的支持和配置、可能会增加服务器的存储和带宽消耗。

总体来说EdgeOne作为一个CDN服务器是非常合格的,值得用户选择和推荐。