WebWorker可通过createImageBitmap和OffscreenCanvas在后台解码、缩放、转码图片(如WebP),主线程用arrayBuffer传输数据,Worker处理后返回Blob或ArrayBuffer,兼顾性能与兼容性。

WebWorker 本身不能直接操作 DOM 或使用 Canvas,但可以配合 createImageBitmap(支持 WebP、JPEG、PNG 等)和 OffscreenCanvas(需浏览器支持)在 Worker 中完成图片解码、缩放、格式转换等计算密集型任务,从而避免阻塞主线程。关键在于:不操作 DOM、用可序列化的数据(如 ArrayBuffer、Blob)通信、利用现代图像 API。
1. 图片数据如何传入 Worker
不能直接传 <img> 或 URL(Worker 无 fetch 权限?错——Worker 支持 fetch,但跨域需注意;更推荐主线程加载后传二进制)。最佳方式是:
- 主线程用
fetch(url).then(r => r.arrayBuffer())获取原始字节,再用postMessage(arrayBuffer, [arrayBuffer])传输(转移所有权,高效) - 若图片来自文件输入,用
file.arrayBuffer()后同上 - 避免传 base64 字符串(体积膨胀 33%,解析慢)
2. Worker 内解码并转为目标格式(如 WebP)
核心依赖两个 API:
-
createImageBitmap(blobOrArrayBuffer):异步解码为 GPU/内存优化的位图(支持 WebP、AVIF、JPEG 等,无需 canvas) -
OffscreenCanvas:创建离屏画布,ctx.drawImage(bitmap, ...)绘制,再调用toBlob(callback, 'image/webp', 0.8)导出(Chrome 69+、Firefox 113+、Safari 16.4+ 支持)
示例 Worker 代码片段:
立即学习“前端免费学习笔记(深入)”;
self.onmessage = async function(e) {
const { data, width, height, quality = 0.8 } = e.data;
try {
// 1. 解码为 ImageBitmap
const bitmap = await createImageBitmap(data);
// 2. 创建 OffscreenCanvas 并绘制(可选:缩放)
const offscreen = new OffscreenCanvas(width || bitmap.width, height || bitmap.height);
const ctx = offscreen.getContext('2d');
ctx.drawImage(bitmap, 0, 0, offscreen.width, offscreen.height);
// 3. 导出为 WebP Blob
const blob = await offscreen.convertToBlob({
type: 'image/webp',
quality
});
// 4. 将 Blob 转 ArrayBuffer 传回(或直接 postMessage(blob) —— 需 transfer)
const arrayBuffer = await blob.arrayBuffer();
self.postMessage({ id: e.data.id, result: arrayBuffer }, [arrayBuffer]);
} catch (err) {
self.postMessage({ id: e.data.id, error: err.message });
}
};
3. 主线程接收并保存/显示结果
收到 ArrayBuffer 后,可:
- 构造
new Blob([arrayBuffer], {type: 'image/webp'}),生成 URL 用于<img src="..."> - 触发下载:
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'converted.webp'; a.click(); - 批量处理时,用
Promise.all()协调多个 Worker 任务,避免洪水式 postMessage
4. 兼容性与降级策略
并非所有浏览器都支持 OffscreenCanvas.convertToBlob 或 WebP 编码:
- 检查支持:
typeof OffscreenCanvas !== 'undefined' && 'convertToBlob' in OffscreenCanvas.prototype - 降级方案:Worker 内用纯 JS 编码库(如 webpjs 的 encoder 分支,或 SheetJS/codex),但性能差、体积大,仅作备用
- 服务端兜底:将 ArrayBuffer 上传至轻量 API(如 /api/convert),由后端完成编码并返回链接



















