告别页面卡死!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

相关推荐
扉伟庆15 小时前
API 网关真流式改造实战:长文翻译首字延迟从 15 秒级降到亚秒级
性能优化·sse·api网关·deepseek·流式输出
晏宁科技YaningAI19 小时前
企业通信系统技术规划方法:从业务需求到可演进架构
网络·性能优化·架构·gateway·paas
天空之城--1 天前
过去一周Android行业动态:编码技术与综合趋势精选
android·flutter·性能优化·kotlin·android jetpack
爱喝水的鱼丶1 天前
SAP-ABAP:SAP学习分享:深入理解事务码ME32K——更改采购合同
性能优化·sap·abap·业务学习·开发交流·交流学习·采购合同
爱喝水的鱼丶1 天前
SAP-ABAP:ABAP 用户出口开发规范与避坑指南:10 类典型错误与运维方案
运维·性能优化·sap·abap·增强·经验交流·出口
爱喝水的鱼丶1 天前
SAP-ABAP:BAdI 上下文数据获取与交互:标准数据读取与修改逻辑实现
运维·性能优化·sap·abap·增强·经验交流·badi
迪飞特科技2 天前
《MyBatis 批量插入性能优化的 5 个关键参数配置》
android·性能优化·mybatis
寻求出路的程序媛2 天前
分布式 & 高性能 & 高可用 体系、学习重点、面试点
分布式·后端·面试·性能优化
JMchen1232 天前
【Android 性能优化实战 60 讲】04 Memory Profiler 高阶玩法:深剖堆内存原理,实战定位 Kotlin 闭包隐式泄漏
android·性能优化·kotlin·实战·源码分析·内存泄漏·memory profiler