网络请求过程中性能优化
这里只是列出一些优化方向,优化点,主要是网络请求过程中、页面加载渲染和JavaScript脚本的优化
网络请求过程中的优化点
减少 HTTP 请求数量
每次网络请求都会产生一定的开销,可以通过以下方法优化:
- 合并请求:将多个相关接口合并,减少重复请求。
- 按需请求:只请求当前页面需要的数据。
- 避免重复请求:对相同的请求进行缓存或复用。
- 资源复用:相同的 JS、CSS 等静态资源尽量共享浏览器缓存。
注意:使用 HTTP/2、HTTP/3 后,不必为了减少请求数量而盲目合并所有 JS、CSS 文件。合理拆分资源更有利于缓存和按需加载。
减小资源体积
资源体积越小,通常下载速度越快。
| 优化方式 | 说明 |
|---|---|
| Gzip / Brotli 压缩 | 压缩 HTML、CSS、JS 等文本资源 |
| 代码压缩 | 删除注释、空格等不必要内容 |
| Tree Shaking | 移除未使用的代码 |
| 图片压缩 | 减少图片文件大小 |
| 图片格式优化 | 优先考虑 WebP、AVIF 等现代格式 |
| 字体优化 | 使用 WOFF2、字体子集化等方式 |
| 按需打包 | 避免将所有依赖打包进首页 |
例如,使用 Vite 构建生产项目时,通常会自动压缩 JS、CSS,并支持 Tree Shaking。
使用浏览器缓存
利用缓存避免重复下载资源。
| 缓存类型 | 说明 |
|---|---|
| 强缓存 | 资源未过期时,直接使用本地缓存,不需要请求服务器确认 |
| 协商缓存 | 向服务器验证资源是否发生变化,未变化时返回 304 |
| 应用层缓存 | 使用内存、Cache API 等保存和复用数据 |
实际项目中,常见的缓存策略是:
- HTML:及时验证是否有更新。
- 带内容哈希的 JS、CSS、图片:设置较长时间的强缓存。
- API 数据:根据业务特点设置缓存策略。
使用 CDN 加速
CDN(内容分发网络)可以将静态资源分发到不同地区的节点,让用户从距离较近的节点获取资源。
常见的 CDN 资源包括图片、字体、CSS、JavaScript 等。
CDN 的主要作用是减少传输延迟、减轻源站压力、提高资源访问速度。
优化请求时机和优先级
不是所有资源都需要在页面打开时立即请求。
- 预加载(preload):提前加载当前页面即将用到的关键资源。
- 预连接(preconnect):提前建立与重要跨域服务器的连接。
- 懒加载(lazy loading):非首屏资源等到需要时再加载。
- 预获取(prefetch):浏览器空闲或合适时机,提前获取未来可能使用的资源。
<!-- 预连接到资源服务器 --><link rel="preconnect" href="https://cdn.example.com" />
<!-- 预加载关键字体 --><link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin/>
<!-- 非首屏图片懒加载 --><img src="/images/banner-2.webp" loading="lazy" alt="banner" />注意:首屏关键图片一般不建议使用 loading="lazy",否则可能延迟首屏显示。
6. 优化接口请求
接口本身也会影响页面性能。
- 避免接口重复调用。
- 对搜索输入等高频操作使用防抖。
- 对不再需要的请求使用
AbortController取消。 - 使用分页加载,避免一次返回过多数据。
- 优化后端数据库查询,缩短接口响应时间。
例如搜索建议:
let timer;
function handleSearch(keyword) { clearTimeout(timer);
timer = setTimeout(() => { fetch(`/api/search?q=${encodeURIComponent(keyword)}`); }, 300);}用户连续输入时,不必每输入一个字符就立即发送一次请求。
页面加载渲染和JavaScript脚本中的优化点
优化页面首次渲染
浏览器渲染页面的主要过程:
常见优化方式:
- 优先加载关键资源:首屏需要的 CSS、字体、图片优先加载。
- 减少阻塞资源:非关键 JavaScript 延迟执行,减少影响首屏渲染的资源。
- 减少 DOM 数量:避免创建大量无意义的嵌套节点。
- 使用 SSR / SSG:适合的场景可以提前生成 HTML,减少首屏等待客户端 JavaScript 渲染的时间。
- 避免不必要的重定向:缩短页面开始加载的等待时间。
尤其需要关注首屏最大内容元素(LCP)的加载时间。
优化 JavaScript 加载与执行
普通的 JavaScript 脚本可能阻塞 HTML 解析。
可以通过 async、defer 优化。
<!-- 普通脚本:执行时阻塞 HTML 解析 --><script src="a.js"></script>
<!-- async:并行下载,下载完成后尽快执行 --><script async src="b.js"></script>
<!-- defer:并行下载,HTML 解析完成后按顺序执行 --><script defer src="c.js"></script>
<!-- ES Module:默认具有类似 defer 的行为 --><script type="module" src="main.js"></script>| 对比 | 普通脚本 | async | defer |
|---|---|---|---|
| 并行下载 | ❌ | ✅ | ✅ |
| 执行时可能阻塞 HTML 解析 | ✅ | ✅ | ❌ |
| 保证多个脚本按文档顺序执行 | ✅ | ❌ | ✅ |
| 适用场景 | 必须立即执行 | 独立脚本 | 有依赖关系的脚本 |
实际开发中,推荐使用 defer 或 ES Module 加载需要操作 DOM 的应用脚本。
减少重排和重绘
- 重排(Reflow / Layout):元素尺寸、位置等发生变化,浏览器需要重新计算布局。
- 重绘(Repaint):元素外观发生变化,需要重新绘制相关内容。
常见优化方式:
- 避免频繁修改元素尺寸、位置。
- 避免在循环中反复读取布局信息后立即修改样式。
- 批量修改 DOM 或 CSS。
- 对动画优先使用
transform、opacity,减少布局计算。
例如:
/* 不推荐:动画过程中可能触发布局计算 */.box { transition: left 0.3s;}
.box:hover { left: 100px;}
/* 推荐:使用 transform 实现位移 */.box { transition: transform 0.3s;}
.box:hover { transform: translateX(100px);}减少 JavaScript 主线程阻塞
JavaScript 中存在大量同步计算时,会阻塞主线程,影响页面交互和绘制。
常见优化方式:
- 拆分长任务:避免一个同步任务持续执行过长时间。
- 使用 Web Worker:将适合的计算密集型任务放到工作线程。
- 按需加载模块:使用动态
import()加载暂时用不到的代码。 - 减少第三方脚本:避免加载不必要的统计、广告和其他外部脚本。
例如:
// 按需加载模块const { calculate } = await import('./calculate.js');
calculate();需要注意:async/await 不能使大量同步计算自动变成非阻塞任务。对于复杂计算,可以考虑 Web Worker。
优化高频事件处理
scroll、resize、pointermove 等事件可能频繁触发。
可以使用:
| 优化方式 | 适用场景 |
|---|---|
| 防抖(debounce) | 搜索框输入、窗口大小变化后的计算 |
| 节流(throttle) | 滚动监听、连续拖拽计算 |
| requestAnimationFrame | 跟随浏览器刷新节奏更新动画 |
| passive 事件监听 | 不需要阻止默认滚动行为的触摸、滚轮监听 |
例如:
let ticking = false;
window.addEventListener('scroll', () => { if (ticking) return;
ticking = true;
requestAnimationFrame(() => { console.log(window.scrollY); ticking = false; });}, { passive: true });优化长列表渲染
当页面需要展示大量数据时,例如一次渲染 10000 条数据,会产生较多 DOM 节点。
可以使用:
- 分页加载:每次只加载部分数据。
- 无限滚动:滚动到底部时继续加载。
- 虚拟列表(Virtual List):只渲染可视区域及附近的列表项。
其中虚拟列表适合大量数据的滚动场景,能显著减少实际 DOM 节点数量。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














