当前位置: 首页 > news >正文

JavaScript 性能优化实战(易懂版)

JavaScript 性能优化实战(易懂版)

适用对象:前端与全栈工程师。原则:先测量、再优化、可回归。

目录

  • TL;DR 快速清单
    1. 度量与预算
    1. 网络与缓存优化
    1. 构建与代码分割
    1. 运行时与调度
    1. DOM 渲染优化
    1. 内存与泄漏
    1. 并行与重活卸载
    1. Node.js 端优化
    1. 诊断剧本
  • 附录:工具与参考

TL;DR 快速清单

  • 指标:LCP < 2.5s,INP < 200ms,CLS < 0.1
  • 传输:HTTP/2/3 + CDN + Brotli;预连接/预加载关键资源
  • 缓存:静态资源指纹 + immutable;HTML 短缓存 + ETag
  • 包体:首屏 JS ≤ 150–200KB gzip;路由级代码分割;移除大依赖
  • 渲染:transform/opacity 动画;列表虚拟化;被动事件 + 节流/防抖
  • 调度:rAF/Idle/切片;避免长任务阻塞主线程
  • 内存:清理监听/计时器;WeakMap;LRU 缓存
  • 并行:Web Worker + Transferable;OffscreenCanvas
  • 回归:web-vitals RUM + Lighthouse CI + Bundle 预算

1. 度量与预算

核心指标与采集(RUM)

// 使用 web-vitals/attribution 采集 LCP/INP/CLS(含归因)
import { onLCP, onINP, onCLS } from 'web-vitals/attribution';const send = (m) => {navigator.sendBeacon('/vitals', JSON.stringify({name: m.name, value: m.value, id: m.id,path: location.pathname, ts: Date.now(),attribution: m.attribution}));
};onLCP(send, { reportAllChanges: true });
onINP(send, { reportAllChanges: true });
onCLS(send, { reportAllChanges: true });

性能预算建议

  • 首屏 JS(可执行)≤ 150–200KB gzip
  • LCP 资源(图/字体)≤ 100KB;关键请求数 ≤ 6
  • CI 设置:Lighthouse 得分门槛 + bundle 体积上限

2. 网络与缓存优化

HTML 预连接/预加载与图片懒加载

<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<link rel="preload" as="style" href="/styles.css">
<link rel="preload" as="script" href="/entry.js" crossorigin>
<img src="hero.avif" srcset="hero@2x.avif 2x" alt="hero" loading="lazy" decoding="async">

按用户意图预取

// 悬停时预取下一步页面资源
const prefetch = (href, as) => {const l = document.createElement('link');l.rel = 'prefetch'; l.href = href; if (as) l.as = as;document.head.appendChild(l);
};
document.addEventListener('mouseover', e => {const more = e.target.closest('#more');if (more) prefetch('/page/product.js', 'script');
}, { passive: true });

Service Worker:静态 Cache First + API Stale-While-Revalidate

// sw.js
const STATIC = 'static-v1';
self.addEventListener('install', e => {e.waitUntil(caches.open(STATIC).then(c => c.addAll(['/', '/index.html', '/styles.css', '/entry.js'])));self.skipWaiting();
});
self.addEventListener('activate', e => {e.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(k => k !== STATIC).map(k => caches.delete(k)))).then(() => self.clients.claim()));
});
self.addEventListener('fetch', e => {const req = e.request; if (req.method 
http://www.xdnf.cn/news/1333315.html

相关文章:

  • 【电气工程学习】
  • (nice!!!)(LeetCode 每日一题) 1277. 统计全为 1 的正方形子矩阵 (动态规划)
  • Qt5.9.9 + Windows API 开发系统监控工具 - 教学级项目实战
  • 项目各功能介绍
  • linux下MySQL安装与卸载
  • Tomcat 性能优化终极指南
  • 餐饮灶头:后厨效率与菜品稳定的核心载体
  • Linux《进程间通信(下)》
  • 海量数据测试指南与实战
  • 【PostgreSQL内核学习:WindowAgg 节点对 Tuplestore 的复用机制】
  • 超大型公共场所的智慧守护者——人脸动态识别与管理系统
  • Temu美国站大规模扫号封店:虚假本土店遭批量封禁,如何规避?
  • 心路历程-了解网络相关知识
  • 【C2000常见问题】当板子处于强电噪声环境下,或带重载时C2000芯片的PWM发波会出现异常,导致炸管。
  • Vue2封装Axios
  • 8.20网络编程——sqlite3数据库
  • LeetCode 刷题【47. 全排列 II】
  • 【Linux系统】匿名管道以及进程池的简单实现
  • 在 React 中,​父子组件之间的通信(传参和传方法)
  • 大语言模型研究进展
  • Elasticsearch 写入全链路:从单机到集群
  • sfc_os!SfcValidateCatalogs函数分析之syssetup.inf中的[ProductCatalogsToInstall]
  • ansible playbook 实战案例roles | 实现基于 IHS 的 AWStats 访问监控系统
  • 第R6周:LSTM实现糖尿病探索与预测
  • [特殊字符] 小豆包 API 聚合平台:让 AI 接入更简单、更高效
  • 【数据结构之二叉树】
  • 【0基础PS】图片格式
  • Java常用类:编程世界的瑞士军刀
  • Web网站的运行原理1
  • JAVA:MyBatis 核心组件详解的技术指南