瀏覽器|瀏覽器多線程離屏渲染壓縮打包方案

瀏覽器|瀏覽器多線程離屏渲染壓縮打包方案


最近朋友跟我交流了一個場景 , 他有需求要用瀏覽器實時生成上萬個二維碼并打包壓縮 。 現在功能是實現了 , 就是耗時長 , 而且一旦開始生成之后 , 頁面卡頓的很厲害 。
我一聽應該是 大量的 渲染 轉化壓縮 這類的計算阻塞了 Js執行主線程 導致的 , 于是開始嘗試對方案進行優化 。
首先先復現Js主線程方案
這個方案心智負擔最低 , 無非是 Canvas 渲染轉化為 blob/(or others) jszip 添加 blob 并進行壓縮 最后下載保存 , 執行的代碼摘要如下:
import JSZip from 'jszip'async function download(){    // canvas do sth        const zip = new JSZip()    await new Promise((resolve)=>{        canvas.toBlob((blob) => {            zip.file(filename blob!)            resolve(blob)        )    )    const content = await zip.generateAsync(        {          type: 'blob'            )    saveAs(content zipName)
實現是非常簡單的 。 筆者也復現了生成 10000 個二維碼的 case , 在 qrcode 的 errorLevel 為 low  不進行額外壓縮的情況下 。
每次生成圖片大約 3-4kb(取決于攜帶參數的大小)生成時間約為 190257.10ms 壓縮時間為 13531ms 總耗時 203788.10ms 。
后來經過反復測試 , 得出下列幾個影響因素:

  • 壓縮等級越高 , 壓縮越慢
  • 生成圖片體積越大 , 生成速度越慢 , 壓縮速度也越慢
另外像這類的高耗時的工作任務 , 一定要添加 onProgress 這樣一個 hook , 方便用戶自定義進度條來優化體驗 , 同時也要防止用戶誤操作造成功虧一簣 。
Worker多線程壓縮
既然現在主線程被阻塞了 , 我們自然而然就想到了 Web Worker 于是筆者使用它來進行壓縮圖片的工作 。
在挑選測試素材時 , 使用了一張 16MB 的圖片 , 嘗試下來 , 壓縮時間顯著高于圖片的生成時間 。 (體積較小圖片其實是沒有必要的 , 主線程本身壓縮速度足夠快)
worker 代碼摘要如下:
// main.worker.tsimport JSZip from 'jszip'const worker: Worker = self as anyasync function doZip (arraybuffer: ArrayBuffer) {  const zip = new JSZip()  const filename = 'test.png'  const blob = new Blob([arraybuffer
)  zip.file(filename blob)  const content = await zip.generateAsync(    {      type: 'arraybuffer'        ({ percent ) => {      // 壓縮進度條      const event: MainWorkerEventData = {        type: 'percent'        percent            worker.postMessage(event)      )  const finish: MainWorkerEventData = {    type: 'save'    content: content    worker.postMessage(finish [content

相關經驗推薦