1419 字
7 分钟
Web 性能优化完全指南:从浏览器原理到性能指标监控

Web 性能优化完全指南:从浏览器原理到性能指标监控#

前言:性能是用户体验的核心。一个加载缓慢的网站会导致用户流失、转化率下降。这篇文章将从浏览器原理出发,系统讲解 Web 性能优化的方方面面。


一、浏览器渲染原理#

1.1 关键渲染路径#

浏览器将 HTML、CSS、JavaScript 转换为屏幕上的像素,经历以下步骤:

HTML → DOM Tree
CSS → CSSOM Tree
Render Tree
Layout (Reflow)
Paint
Composite

详细过程:

  1. 解析 HTML 构建 DOM

    • 遇到 <script> 会阻塞解析(除非有 defer/async)
    • 遇到 CSS 会请求并解析
  2. 解析 CSS 构建 CSSOM

    • CSS 是阻塞渲染的资源
    • 内联 CSS 可以避免网络请求
  3. 合并 DOM 和 CSSOM 形成 Render Tree

    • 只包含可见元素(排除 display: none)
  4. Layout(布局/回流)

    • 计算每个元素的位置和大小
    • 几何属性变化会触发回流
  5. Paint(绘制)

    • 填充像素
    • 颜色、背景、阴影等属性变化触发重绘
  6. Composite(合成)

    • 将图层合并为最终屏幕图像
    • transform 和 opacity 触发合成

1.2 回流和重绘#

触发回流(Reflow)的属性:

  • width、height、padding、margin
  • border、display、position
  • top、left、right、bottom
  • font-size、line-height
  • 获取 offsetHeight、scrollTop 等

触发重绘(Repaint)的属性:

  • color、background-color
  • border-color、box-shadow
  • text-decoration

优化策略:

// ❌ 错误:多次读写导致多次回流
const height = element.offsetHeight; // 读取
element.style.height = (height + 10) + 'px'; // 写入
const width = element.offsetWidth; // 读取(触发回流)
element.style.width = (width + 10) + 'px'; // 写入
// ✅ 正确:批量读写
const height = element.offsetHeight;
const width = element.offsetWidth;
element.style.cssText = `height: ${height + 10}px; width: ${width + 10}px;`;

二、资源加载优化#

2.1 图片优化#

格式选择:

  • 照片:WebP(比 JPEG 小 25-35%)
  • 透明背景:WebP 或 PNG
  • 动画:WebP 或 AVIF
  • 图标:SVG

响应式图片:

<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="描述" loading="lazy">
</picture>
<!-- 不同尺寸 -->
<img
srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
src="fallback.jpg"
alt="描述"
>

懒加载:

<!-- 原生懒加载 -->
<img src="placeholder.jpg" data-src="real.jpg" loading="lazy" alt="">
<!-- Intersection Observer -->
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
</script>

2.2 JavaScript 优化#

代码分割:

// 路由级别分割
const Home = () => import('./views/Home.vue');
const About = () => import('./views/About.vue');
// 组件级别分割
const HeavyComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
);

Tree Shaking:

// ✅ 使用具名导入,支持 Tree Shaking
import { map, filter } from 'lodash-es';
// ❌ 避免全量导入
import _ from 'lodash';

延迟加载非关键 JS:

<!-- async: 并行下载,下载完立即执行 -->
<script src="analytics.js" async></script>
<!-- defer: 并行下载,HTML解析完执行 -->
<script src="app.js" defer></script>
<!-- type="module": 自动 defer -->
<script type="module" src="app.js"></script>

2.3 CSS 优化#

关键 CSS 内联:

<head>
<!-- 关键 CSS 直接内联 -->
<style>
/* 首屏必需的样式 */
body { margin: 0; font-family: sans-serif; }
.hero { height: 100vh; background: #000; }
</style>
<!-- 非关键 CSS 异步加载 -->
<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>
</head>

CSS 压缩和 Purge:

tailwind.config.js
module.exports = {
purge: ['./src/**/*.{vue,js,ts}'],
// 生产环境自动移除未使用的 CSS
};

三、缓存策略#

3.1 HTTP 缓存#

# 强缓存(不会发请求到服务器)
Cache-Control: max-age=31536000, immutable
# 协商缓存(会发请求验证)
Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT
ETag: "33a64df5"

最佳实践:

  • HTML:no-cache(总是获取最新)
  • JS/CSS:永久缓存,使用内容哈希命名
  • 图片/字体:长期缓存

3.2 Service Worker 缓存#

service-worker.js
const CACHE_NAME = 'v1';
const urlsToCache = [
'/',
'/styles.css',
'/app.js'
];
// 安装时缓存
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
);
});
// 拦截请求
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// 缓存优先
if (response) return response;
return fetch(event.request);
})
);
});

四、Core Web Vitals#

Google 提出的三个核心性能指标:

4.1 LCP(Largest Contentful Paint)#

定义: 最大内容绘制时间,衡量首屏加载速度。

目标: < 2.5 秒

优化方法:

  • 优化服务器响应时间
  • 预加载关键资源
  • 压缩图片
  • 使用 CDN
<!-- 预加载 LCP 图片 -->
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">

4.2 FID(First Input Delay)/ INP#

定义: 首次输入延迟 / 交互到下一帧绘制,衡量交互响应性。

目标: < 100 毫秒

优化方法:

  • 拆分长任务
  • 使用 Web Workers
  • 延迟非关键 JS
// 拆分长任务
async function processLargeArray(data) {
const chunkSize = 100;
for (let i = 0; i < data.length; i += chunkSize) {
await new Promise(resolve => {
requestIdleCallback(() => {
processChunk(data.slice(i, i + chunkSize));
resolve();
});
});
}
}

4.3 CLS(Cumulative Layout Shift)#

定义: 累积布局偏移,衡量视觉稳定性。

目标: < 0.1

优化方法:

  • 图片设置尺寸
  • 广告位预留空间
  • 避免插入内容到已有内容上方
<!-- 预留图片空间 -->
<img src="photo.jpg" width="800" height="600" alt="">
<!-- 预留广告位 -->
<div style="min-height: 250px;">
<!-- 广告代码 -->
</div>

五、性能监控#

5.1 Web Vitals 库#

import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
// 发送到分析服务
navigator.sendBeacon('/analytics', body);
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

5.2 Performance API#

// 获取性能数据
const perfData = performance.getEntriesByType('navigation')[0];
console.log('DNS 查询:', perfData.domainLookupEnd - perfData.domainLookupStart);
console.log('TCP 连接:', perfData.connectEnd - perfData.connectStart);
console.log('TTFB:', perfData.responseStart - perfData.requestStart);
console.log('DOM 解析:', perfData.domContentLoadedEventEnd - perfData.domLoading);
console.log('资源加载:', perfData.loadEventEnd - perfData.domContentLoadedEventEnd);
// 资源加载详情
const resources = performance.getEntriesByType('resource');
resources.forEach(r => {
console.log(`${r.name}: ${r.duration}ms`);
});

六、性能优化清单#

加载优化#

  • 启用 HTTP/2
  • 使用 CDN
  • 压缩资源(Gzip/Brotli)
  • 图片懒加载
  • 使用 WebP 格式
  • 内联关键 CSS
  • 延迟加载非关键 JS
  • 资源预加载/预连接

运行时优化#

  • 避免强制同步布局
  • 使用 transform 和 opacity 动画
  • 虚拟列表渲染大量数据
  • 使用 requestAnimationFrame
  • Web Workers 处理复杂计算

缓存优化#

  • 静态资源长期缓存
  • Service Worker 缓存
  • 合理使用 LocalStorage/IndexedDB

七、总结#

性能优化是一个持续的过程:

  1. 测量:使用 Lighthouse、Web Vitals 评估现状
  2. 优化:针对瓶颈进行优化
  3. 监控:持续监控真实用户性能数据
  4. 迭代:不断优化改进

记住:没有银弹,要根据实际情况选择合适的优化策略。

希望这篇文章能帮助你打造极致性能的 Web 应用!

Web 性能优化完全指南:从浏览器原理到性能指标监控
https://www.oferry.com/posts/a87/
作者
晨平安
发布于
2026-02-27
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00