前言
一般的论坛站点中都会存储大量的图片,图片文件的格式需要根据浏览器的类型来进行适配,返回浏览器可兼容的图片格式,同时最大程度上压缩图片的大小,来节省流量。例如:
● 当用户使用 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属性,指向相应格式的图片地址。
代码
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可以用第二种方法,通过边缘函数进行调整
边缘函数
同样的,我们先新建一个函数,创建步骤同前面一样,这里就不再创建了。
然后点击函数名
点击编辑代码
然后将之前示例给的替换图片格式代码删掉
换成下面自己写的调整图片大小的代码
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服务器是非常合格的,值得用户选择和推荐。