浏览器|浏览器多线程离屏渲染压缩打包方案( 三 )


同时创建 ImageBitmap 的 API: createImageBitmap 方法同时存在 windows 和 workers 中. 它接受各种不同的图像来源 。 例如它可以处理我们最常使用的 HTMLImageElement 对象 。
这里我以 ImageBitmap 为例构建 Web Worker 部分代码:
// main.work.tsasync function getCanvasBlob(bitmap: ImageBitmap): Promise<Blob> {    const canvas = new OffscreenCanvas(bitmap.width bitmap.height)    const ctx = canvas.getContext('2d') as OffscreenCanvasRenderingContext2D    ctx.drawImage(bitmap 0 0)    // do sth        return await canvas.convertToBlob()
这部分代码目的在于取代主线程中创建的 HTMLCanvasElement 对象 , 更换为 Web Worker 中创建的 OffscreenCanvas 对象 。
【浏览器|浏览器多线程离屏渲染压缩打包方案】主线程只负责创建 ImageBitmap 和 ArrayBuffer 这类的 Transferable_objects 来和 Worker 进行数据通信 。
并最终 Worker 输出一个 ArrayBuffer 交给主线程组装二进制对象并进行浏览器下载行为 。
优雅的兼容性降级方案
方案主要存在 2 个可能不兼容的点:
OffscreenCanvas
OffscreenCanvas 除了 chormuim 内核的那一批浏览器(chrome.edge)支持较好之外 , 像 FFSafariie 均不支持 (意外的是 opera居然支持)

Web Worker
Web Worker 大部分都支持(包括 ie10+)不过各个浏览器支持的特性存在一些细小的差异 。

兼容标志位
// 是否支持 web workerexport const isSupportWorker = Boolean(window.Worker)// 是否支持 OffscreenCanvasexport const isSupportOffscreenCanvas = Boolean(window.OffscreenCanvas)

  1. 优先去除兼容性最差的OffscreenCanvas
  2. 次级去除 Web Worker  只使用Js主线程
方案示例见
方案总结
优点:
  1. 处理大体积图片的性能更优
  2. 不阻塞主js线程
缺点:
  1. 兼容性差 需要降级方案
  2. 实现相比单线程版本较为复杂 , 心智负担较重 , 容易出bug
  3. 处理小图片可能不如主线程
  4. 不同浏览器性能差异较大 , 难以统一用户体验
源代码和参考文献

相关经验推荐