webp图片必须由工具提前批量生成,js仅负责检测浏览器支持性并智能加载对应格式。通过canvas.toblob判断webp支持,支持时加载.webp,否则fallback到.jpg/.png;构建阶段预转换才能真正减体积,js无法实时转码或替代专业压缩工具。

直接在 JavaScript 中生成或加载 WebP 图片,本身不压缩原始图——关键在于“用 WebP 替代传统格式”,而不是靠 JS 实时转码。浏览器不支持 JS 原生读取 JPEG 再输出 WebP(除非调用后端或 WASM),所以实际路径是:前端控制加载逻辑 + 后端/构建阶段提前转好 WebP 文件 + 兜底兼容。
WebP 文件必须提前生成,JS 负责智能加载
浏览器无法用纯 JS 把一张 JPG “实时转成 WebP 并返回 Blob”(Canvas 导出只支持 PNG/JPEG,不支持 WebP)。因此 WebP 必须由工具提前批量生成(如 cwebp、Sharp、WebPShop 或在线压缩图),JS 的作用是判断环境、选择正确的 URL 加载它。
- 所有 WebP 图片应与原图同名同路径,仅扩展名不同(例如
banner.jpg和banner.webp) - JS 检测浏览器是否支持 WebP(通过 canvas 绘制+toBlob 判断能否生成 webp 类型 blob)
- 支持时加载
.webp链接;不支持时 fallback 到.jpg或.png - 避免在运行时用 JS 解码/重编码图片——这会卡主线程,且体积未必更小
用 Canvas 检测 WebP 支持性(轻量可靠)
这是最常用、无请求、零依赖的检测方式,兼容所有现代浏览器:
- 创建一个
<canvas></canvas>,绘制简单图形 - 调用
canvas.toBlob(callback, 'image/webp') - 若 callback 被触发且 blob.type === 'image/webp',说明支持
- 封装成 Promise 函数,可在页面初始化时调用一次,缓存结果
示例代码片段:
function supportsWebP() {
return new Promise(resolve => {
const canvas = document.createElement('canvas');
canvas.width = 1; canvas.height = 1;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 1, 1);
canvas.toBlob(blob => resolve(blob?.type === 'image/webp'), 'image/webp');
});
}
HTML & JS 中动态切换图片源(兼容落地)
不改 HTML 结构也能生效,适合已有项目渐进优化:
- 给
<img>添加data-src-jpg和data-src-webp属性 - JS 根据支持性,把对应地址赋给
src,再触发自然加载 - 配合
loading="lazy"和 IntersectionObserver 实现懒加载,进一步减少首屏压力 - 对 CSS 背景图,可改用
@supports (background: image-set(...))或 JS 动态写 style
真正减体积靠的是预转换,不是 JS 压缩
JS 无法替代专业图像处理工具。实测数据表明:一张 800KB 的 JPEG,用 cwebp -q 75 转 WebP 后约 520KB(缩减 35%);而 JS 用 canvas 缩放到 80% 宽高 + toDataURL('image/jpeg', 0.7) 只能减到约 650KB,且画质损失更明显。
- 推荐构建时批量转:Webpack 用
webp-loader,Vite 用vite-plugin-imagemin,Nuxt 用nuxt-image - 服务端部署 WebP Server(Golang 实现),自动响应
Accept: image/webp请求,URL 不变,运维透明 - 静态站点可搭配 GitHub Actions,在 push 时用 Sharp 自动转存 WebP 到 /images/webp/ 目录
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











