告别页面卡死!Vue3 + WebWorker 性能优化实战

你遇到过点击按钮后页面直接"假死"的情况吗?Loading 动图定格、按钮点击无效、甚至浏览器弹出"未响应"警告?别慌,这通常是 JS 主线程被密集计算阻塞了。今天,带你用 Web Worker 把这些重活"踢"出主线程,让你的 Vue3 应用丝滑如初!

😱 案发现场:一段代码让浏览器"脑梗"

在 B 端系统中,我们经常会遇到这种需求:

  • 导出 Excel :处理几万条数据的格式化。
  • 图像处理 :前端压缩图片或添加水印。
  • 复杂算法 :加密解密、大数计算(如斐波那契数列)。

很多同学反手就是直接写在组件里:

javascript 复制代码
// ❌ 危险操作:在主线程进行 CPU 密集型计算
function expensiveCalculation() {
  const result = fibonacci(42); // 这里可能要算好几秒
  console.log(result);
}

结果就是: 只要计算还在跑,浏览器的 UI 渲染线程就被挂起。 你的 Loading 圈不转了,用户的鼠标点击没反应了,整个页面像中了定身术一样,就像下图中加载动画卡主了。

💡 救星登场:Web Worker

JavaScript 是单线程的,但浏览器不是! Web Worker 的作用就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。
简单说:主线程负责貌美如花(UI 渲染),Worker 线程负责赚钱养家(脏活累活)。

🛠️ 实战:Vue3 中使用 Web Worker

今天我们就通过一个 斐波那契数列计算 的 Demo,来看看 Worker 到底有多强。
1. 准备 Worker 脚本

首先,我们需要编写一个独立的 JS 文件,它运行在独立的线程中。

javascript 复制代码
// src/utils/webWorker.js
// 监听主线程发来的消息
self.onmessage = function (e) {
  const { type, data } = e.data;

  if (type === "FIBONACCI_CALC") {
    const start = performance.now();
    // 执行耗时计算
    const result = fibonacci(data);
    const time = performance.now() - start;

    // 计算完毕,把结果发回给主线程
    self.postMessage({
      type,
      data: result,
      time: time.toFixed(2)
    });
  }
};

// 递归计算斐波那契数列(故意用性能差的递归来模拟耗时任务)
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

2. 在 Vue 组件中引入

在 Vite 构建的 Vue3 项目中,引入 Worker 非常优雅,只需要加上 ?worker 后缀。

javascript 复制代码
// src/views/func/performance/webWorker.vue
<script setup>
import { ref } from 'vue';
// ✅ Vite 专属写法,简单粗暴
import MyWorker from "@/utils/webWorker.js?worker";

const calculateNum = ref(42);
const loading = ref(false);

const runWorker = () => {
  loading.value = true;

  // 1. 实例化 Worker
  const worker = new MyWorker();

  // 2. 发送任务
  worker.postMessage({
    type: "FIBONACCI_CALC",
    data: calculateNum.value,
  });

  // 3. 接收结果
  worker.onmessage = (e) => {
    const { data, time } = e.data;
    console.log(`计算结果:${data},耗时:${time}ms`);

    // 页面状态照常更新,丝毫不卡!
    loading.value = false;

    // 4. 用完记得销毁,释放内存
    worker.terminate();
  };
};
</script>

3. 效果对比

为了直观展示,我做了一个 帧率计数器 。

方案 A(主线程) :点击开始计算,帧率计数器瞬间 停止跳动 ,浏览器卡死,直到计算结束。用户体验极差!❌

方案 B(Worker) :点击开始计算,后台在狂奔,但前台的帧率计数器 依然流畅跳动 ,Loading 动画丝滑旋转。用户体验满分!✅

📝 核心知识点总结

1. 什么时候用 Worker?

①任何超过 50ms 的纯计算任务。

②大文件上传前的切片、Hash 计算。

③复杂数据的过滤、排序、格式化。

④Canvas 图像像素级处理。
2. 注意事项

①DOM 限制 :Worker 内无法操作 DOM(不能 document.getElementById )。

②通信成本 :主线程和 Worker 之间传递数据是通过拷贝而非共享,传输过③大的数据(如几百 MB 的 JSON)本身也会消耗性能。建议使用 Transferable Objects 传输二进制数据。

④同源策略 :Worker 脚本必须遵守同源策略。
3. Vite 黑科技

a.直接作为模块引入。
import Worker from './worker.js?worker'

b.多个标签页共享同一个 Worker。
import SharedWorker from './worker.js?sharedworker'

源码地址

https://gitee.com/benxiaohai1071/bxh-admin-vue3/blob/master/src/views/func/performance/webWorker.vue

相关推荐
是梦终空2 天前
React Native 性能优化指南
react native·性能优化
侑虎科技3 天前
在UE5中,预测脚步IK实现-PredictFootIK
性能优化·unreal engine
bluceli5 天前
前端性能优化实战指南:让你的网页飞起来
前端·性能优化
冰_河5 天前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
叶智辽7 天前
【Three.js内存管理】那些你以为释放了,其实还在占着的资源
性能优化·three.js
BigByte8 天前
我用 6 个 WASM 编码器干掉了 Canvas.toBlob(),图片压缩率直接提升 15%
性能优化·webassembly·图片资源
DemonAvenger9 天前
Kafka性能调优:从参数配置到硬件选择的全方位指南
性能优化·kafka·消息队列
桦说编程9 天前
实战分析 ConcurrentHashMap.computeIfAbsent 的锁冲突问题
java·后端·性能优化
小马爱打代码10 天前
MySQL性能优化核心:InnoDB Buffer Pool 详解
数据库·mysql·性能优化
顾青10 天前
仅仅一行 CSS,竟让 2000 个节点的页面在弹框时卡成 PPT?
前端·vue.js·性能优化