feat(docs): add performance overview demo component and update content structure
- Create PerformanceOverviewDemo.vue with interactive performance dimension visualization - Update config.mjs to support new component registration - Add new frontend evolution components to theme/index.js - Consolidate stage-0 intro pages into index.md across all locales - Enhance LLM intro documentation with tokenization details
This commit is contained in:
@@ -1,367 +1,133 @@
|
||||
# 前端性能优化:从加载到渲染 (Interactive Guide to Frontend Performance)
|
||||
# 前端性能优化 (Frontend Performance)
|
||||
|
||||
> 💡 **学习指南**:本章节通过交互式演示和实战案例,帮你建立前端性能优化的完整知识体系。性能优化不是玄学,而是一套可测量、可优化的工程方法论。
|
||||
> 💡 **学习指南**:本章节无需深入的算法背景,通过交互式演示带你掌握前端性能优化的核心逻辑。我们将从最直观的页面加载讲起,一直到浏览器底层的渲染机制和缓存策略。
|
||||
|
||||
## 0. 引言:为什么性能很重要?
|
||||
|
||||
**性能就是用户体验。**
|
||||
|
||||
一个页面加载多慢,用户就会流失?研究数据表明:
|
||||
|
||||
- **3 秒法则**:页面加载超过 3 秒,53% 的用户会离开
|
||||
- **0.1 秒延迟**:亚马逊发现页面延迟 0.1 秒,销售额下降 1%
|
||||
- **移动端更敏感**:移动用户对性能的容忍度更低
|
||||
|
||||
性能优化不只是"让页面变快",而是:
|
||||
|
||||
- **提升转化率**:更快的加载 = 更多的订单/注册
|
||||
- **改善 SEO**:搜索引擎优先索引加载快的页面
|
||||
- **降低成本**:优化的资源 = 更少的带宽和服务器成本
|
||||
|
||||
### 0.1 核心性能指标 (Core Web Vitals)
|
||||
|
||||
Google 定义了三个核心性能指标,所有网页都应该达标:
|
||||
<PerformanceOverviewDemo />
|
||||
|
||||
<PerformanceMetricsDemo />
|
||||
|
||||
**关键点**:性能优化要关注真实用户感受到的体验,而不只是技术指标。
|
||||
## 0. 引言:从 "能用" 到 "好用"
|
||||
|
||||
### 0.2 性能预算 (Performance Budget)
|
||||
如果把访问网页比作去餐厅**吃饭**,那么:
|
||||
|
||||
**性能预算**是为项目设定的性能限制,比如:
|
||||
- **加载 (Loading)** 就是食材(HTML/CSS/JS/图片)从仓库(服务器)运送到厨房(浏览器)的过程。
|
||||
- **渲染 (Rendering)** 就是厨师(浏览器引擎)把食材加工成美味菜肴(页面)的过程。
|
||||
- **交互 (Interaction)** 就是服务员响应你的需求(点击、滚动)。
|
||||
|
||||
- JavaScript 文件不超过 200KB
|
||||
- 首屏加载时间不超过 2 秒
|
||||
- 总资源大小不超过 1MB
|
||||
**前端性能优化**的本质,就是为了让这三个过程**更快、更顺畅**。
|
||||
|
||||
**为什么需要预算?**
|
||||
它的核心任务只有一个:**最大限度地减少用户的等待时间。**
|
||||
|
||||
- 防止项目膨胀:随着功能增加,性能很容易恶化
|
||||
- 团队协作规范:新功能上线前必须通过性能检查
|
||||
- 持续优化动力:每次迭代都有改进目标
|
||||
为了实现这个目标,我们需要解决三个核心挑战:
|
||||
|
||||
1. **传输**:怎么把“食材”运得更快?(压缩、CDN、懒加载)
|
||||
2. **渲染**:怎么让“厨师”做得更快?(关键渲染路径、重排重绘)
|
||||
3. **记忆**:怎么避免重复劳动?(缓存策略)
|
||||
|
||||
本教程将带你一步步拆解这些优化技巧。
|
||||
|
||||
---
|
||||
|
||||
## 1. 性能分析工具
|
||||
## 1. 第一步:传输 (Loading)
|
||||
|
||||
在优化之前,先学会**测量**。只有找到瓶颈,才能精准优化。
|
||||
在厨师开始做饭之前,首先得有食材。如果运送食材的卡车堵在路上了,厨房里再厉害的大厨也得干瞪眼。
|
||||
|
||||
### 1.1 Chrome DevTools
|
||||
### 1.1 为什么网速快了,网页还是很慢?
|
||||
|
||||
浏览器自带的开发者工具,功能强大:
|
||||
你可能会疑惑:现在的 5G 和光纤这么快,为什么有些网页打开还是很慢?
|
||||
|
||||
**Performance 面板**:
|
||||
原因通常有两个:
|
||||
1. **东西太多**:一张高清大图可能就有 5MB,相当于下载一本书。
|
||||
2. **路太堵**:浏览器同时下载的资源数量是有限的(通常 6 个),就像只有 6 辆小卡车在运货,多出来的得排队。
|
||||
|
||||
- 录制页面运行过程
|
||||
- 查看 FPS(帧率)、CPU 使用率
|
||||
- 分析 JavaScript 执行时间
|
||||
- 找出长任务(Long Tasks,超过 50ms 的 JS 任务)
|
||||
### 1.2 解决方案:瘦身与偷懒
|
||||
|
||||
**Lighthouse 面板**:
|
||||
为了解决这个问题,我们主要用两招:**压缩(瘦身)**和**懒加载(偷懒)**。
|
||||
|
||||
- 一键生成性能报告
|
||||
- 包含性能、可访问性、最佳实践、SEO 等评分
|
||||
- 给出具体优化建议
|
||||
#### 瘦身:图片与代码压缩
|
||||
|
||||
**Network 面板**:
|
||||
图片通常是网页里最大的“胖子”。
|
||||
现代的图片格式(如 WebP, AVIF)就像是采用了高科技压缩技术的压缩包,在画质几乎不变的情况下,体积能减小 30%-70%。
|
||||
|
||||
- 查看所有资源加载时间
|
||||
- 分析瀑布图(Waterfall)
|
||||
- 找出加载慢的资源
|
||||
<ImageOptimizationDemo />
|
||||
|
||||
### 1.2 WebPageTest
|
||||
#### 偷懒:懒加载 (Lazy Loading)
|
||||
|
||||
在线性能测试工具([webpagetest.org](https://webpagetest.org)):
|
||||
“偷懒”在这里是个褒义词。
|
||||
如果用户只在看第一屏的内容,为什么要把底下第十屏的图片也下载下来呢?
|
||||
|
||||
- 多地点测试(全球各地)
|
||||
- 真实浏览器测试(Chrome、Firefox、Safari)
|
||||
- 丰富的测试报告和视频
|
||||
- 可以模拟不同网速(3G、4G)
|
||||
|
||||
### 1.3 PageSpeed Insights
|
||||
|
||||
Google 官方工具([pagespeed.web.dev](https://pagespeed.web.dev)):
|
||||
|
||||
- 基于 Core Web Vitals 评分
|
||||
- 区分移动端和桌面端
|
||||
- 提供字段数据(真实用户数据)和实验室数据
|
||||
|
||||
**关键点**:用数据驱动优化,而不是凭感觉。
|
||||
|
||||
---
|
||||
|
||||
## 2. 加载优化 (Loading Optimization)
|
||||
|
||||
加载优化是性能优化的第一步:让资源更快地到达浏览器。
|
||||
|
||||
### 2.1 资源压缩
|
||||
|
||||
**文本压缩**:使用 Gzip 或 Brotli 压缩 HTML、CSS、JavaScript
|
||||
|
||||
```
|
||||
未压缩: 500 KB
|
||||
Gzip: 150 KB (压缩率 70%)
|
||||
Brotli: 120 KB (压缩率 76%)
|
||||
```
|
||||
|
||||
**开启方法**(Nginx 配置):
|
||||
|
||||
```nginx
|
||||
gzip on;
|
||||
gzip_types text/css application/javascript;
|
||||
gzip_min_length 1000;
|
||||
|
||||
# Brotli 需要额外模块
|
||||
brotli on;
|
||||
brotli_types text/plain text/css application/javascript;
|
||||
```
|
||||
|
||||
**图片压缩**:使用工具(如 ImageOptim、TinyPNG)压缩图片
|
||||
**懒加载**的策略是:**只加载用户看得到的内容**。当用户滚动页面,图片快要出现时,再去下载它。
|
||||
|
||||
<LazyLoadingDemo />
|
||||
|
||||
### 2.2 代码分割 (Code Splitting)
|
||||
|
||||
**问题**:传统打包方式把所有代码打包成一个文件,首屏要下载大量无用代码
|
||||
|
||||
**解决方案**:按路由或功能分割代码,用户只下载当前页面需要的代码
|
||||
|
||||
**示例**(Vite + Vue Router):
|
||||
|
||||
```javascript
|
||||
// 懒加载路由组件
|
||||
const Home = () => import('./views/Home.vue')
|
||||
const About = () => import('./views/About.vue')
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: Home },
|
||||
{ path: '/about', component: About }
|
||||
]
|
||||
```
|
||||
|
||||
**效果**:
|
||||
|
||||
- 首页只加载 100KB(而不是 500KB)
|
||||
- 用户访问 /about 时才加载额外代码
|
||||
- 整体首屏时间减少 60%
|
||||
|
||||
### 2.3 Tree Shaking
|
||||
|
||||
**Tree Shaking**:移除未使用的代码
|
||||
|
||||
**示例**:
|
||||
|
||||
```javascript
|
||||
// 整个 lodash 库:70 KB
|
||||
import _ from 'lodash'
|
||||
|
||||
// 只用某个函数:2 KB
|
||||
import debounce from 'lodash/debounce'
|
||||
```
|
||||
|
||||
**Tree Shaking 原理**:
|
||||
|
||||
- ES Module 的 `import/export` 是静态结构
|
||||
- 打包工具(Webpack、Vite)可以分析哪些代码被使用
|
||||
- 未使用的代码在打包时被删除
|
||||
|
||||
### 2.4 预加载 (Preloading)
|
||||
|
||||
**预加载关键资源**:告诉浏览器提前加载重要资源
|
||||
|
||||
```html
|
||||
<!-- 预加载关键 CSS -->
|
||||
<link rel="preload" href="critical.css" as="style" />
|
||||
|
||||
<!-- 预加载字体 -->
|
||||
<link rel="preload" href="font.woff2" as="font" crossorigin />
|
||||
|
||||
<!-- DNS 预解析 -->
|
||||
<link rel="dns-prefetch" href="https://api.example.com" />
|
||||
|
||||
<!-- 预连接 -->
|
||||
<link rel="preconnect" href="https://cdn.example.com" />
|
||||
```
|
||||
|
||||
**优先级**:
|
||||
|
||||
- `preload`:立即下载(但可能抢占关键资源)
|
||||
- `prefetch`:空闲时下载(适合下一页资源)
|
||||
- `preconnect`:提前建立 TCP 连接
|
||||
|
||||
### 2.5 CDN 加速
|
||||
|
||||
**CDN(Content Delivery Network)**:内容分发网络
|
||||
|
||||
**工作原理**:
|
||||
|
||||
- 把静态资源部署到全球各地的服务器
|
||||
- 用户从最近的服务器下载资源
|
||||
- 减少网络传输延迟
|
||||
|
||||
**使用建议**:
|
||||
|
||||
- 图片、字体、CSS、JS 等静态资源放 CDN
|
||||
- 使用公共 CDN(如 unpkg、jsDelivr)加载第三方库
|
||||
- 大型网站使用自建 CDN 或商业 CDN(如 Cloudflare)
|
||||
|
||||
**效果**:
|
||||
|
||||
- 国内用户加载速度提升 50%-80%
|
||||
- 海外用户体验显著改善
|
||||
**关键点**:永远不要让用户下载他们不需要(或者暂时不需要)的资源。
|
||||
|
||||
---
|
||||
|
||||
## 3. 渲染优化 (Rendering Optimization)
|
||||
## 2. 核心难题:渲染 (Rendering)
|
||||
|
||||
资源加载完成后,浏览器要"画"出页面。渲染优化让这个过程更快。
|
||||
食材运到了,接下来压力给到了厨师(浏览器)。
|
||||
|
||||
### 3.1 关键渲染路径 (Critical Rendering Path)
|
||||
### 2.1 浏览器的“单线程”困境
|
||||
|
||||
**浏览器渲染流程**:
|
||||
浏览器里的大厨(主线程)非常忙,他不仅要负责**画页面**(布局、绘制),还要负责**响应用户**(点击事件、JS 逻辑)。
|
||||
最糟糕的是,他只有**一个人**(单线程)。
|
||||
|
||||
1. **解析 HTML** → 构建 DOM 树
|
||||
2. **解析 CSS** → 构建 CSSOM 树
|
||||
3. **合并 DOM + CSSOM** → 构建渲染树
|
||||
4. **布局(Layout)**:计算元素位置和大小
|
||||
5. **绘制(Paint)**:绘制像素
|
||||
6. **合成(Composite)**:合成图层
|
||||
如果你让他在切菜(运行复杂的 JS 计算)的时候,顾客(用户)想点菜(点击按钮),他是没法理你的。这就导致了**卡顿**。
|
||||
|
||||
**关键点**:每一步都可能成为性能瓶颈。
|
||||
### 2.2 关键渲染路径 (Critical Rendering Path)
|
||||
|
||||
### 3.2 DOM 优化
|
||||
为了让用户尽快看到东西,浏览器制定了一套标准的工作流程,我们叫它**关键渲染路径**:
|
||||
|
||||
**减少 DOM 操作**:DOM 操作很慢,批量处理
|
||||
1. **HTML -> DOM**:把菜谱读懂,列出食材清单。
|
||||
2. **CSS -> CSSOM**:搞清楚每种食材怎么处理(颜色、大小)。
|
||||
3. **Render Tree**:把清单和处理方法结合,决定最后上桌的菜。
|
||||
4. **Layout (排版)**:决定每个菜摆在盘子的哪个位置。
|
||||
5. **Paint (绘制)**:最后淋上酱汁,上色。
|
||||
|
||||
**示例**(低效):
|
||||
<CriticalRenderingPathDemo />
|
||||
|
||||
```javascript
|
||||
// 每次循环都触发重排
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
document.body.innerHTML += `<div>${i}</div>`
|
||||
}
|
||||
```
|
||||
### 2.3 避坑指南:重排 (Reflow) 与重绘 (Repaint)
|
||||
|
||||
**优化**:
|
||||
在这个流程中,最累人的步骤是 **Layout (排版)**。
|
||||
|
||||
```javascript
|
||||
// 使用文档片段,只触发一次重排
|
||||
const fragment = document.createDocumentFragment()
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const div = document.createElement('div')
|
||||
div.textContent = i
|
||||
fragment.appendChild(div)
|
||||
}
|
||||
document.body.appendChild(fragment)
|
||||
```
|
||||
|
||||
**使用虚拟 DOM**:
|
||||
|
||||
- Vue、React 使用虚拟 DOM 减少真实 DOM 操作
|
||||
- 批量更新,减少重排次数
|
||||
|
||||
### 3.3 CSS 优化
|
||||
|
||||
**减少 CSS 大小**:
|
||||
|
||||
- 移除未使用的 CSS(使用 PurgeCSS)
|
||||
- 压缩 CSS(移除空格、注释)
|
||||
|
||||
**优化 CSS 选择器**:
|
||||
|
||||
```css
|
||||
/* 慢:从右向左匹配 */
|
||||
.container div ul li a {
|
||||
}
|
||||
|
||||
/* 快:使用类选择器 */
|
||||
.link {
|
||||
}
|
||||
```
|
||||
|
||||
**关键 CSS 内联**:
|
||||
|
||||
- 把首屏需要的 CSS 内联到 HTML
|
||||
- 减少渲染阻塞
|
||||
|
||||
```html
|
||||
<style>
|
||||
/* 首屏关键 CSS */
|
||||
.header {
|
||||
}
|
||||
.hero {
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 3.4 重排与重绘
|
||||
- **重排 (Reflow)**:如果你改变了元素的大小或位置,浏览器通过重新计算所有元素的位置。这就像因为桌子移了一下,整个餐厅的椅子都要重新摆一遍。**非常消耗性能!**
|
||||
- **重绘 (Repaint)**:如果你只是改变了颜色,浏览器只需要重新上色。这就像给桌布换个颜色,简单多了。
|
||||
|
||||
<ReflowRepaintDemo />
|
||||
|
||||
**触发重排的操作**:
|
||||
|
||||
- 改变元素大小、位置
|
||||
- 添加/删除 DOM 元素
|
||||
- 改变字体大小
|
||||
- 改变窗口大小
|
||||
|
||||
**触发重绘的操作**:
|
||||
|
||||
- 改变颜色
|
||||
- 改变背景
|
||||
- 改变边框样式
|
||||
|
||||
**优化建议**:
|
||||
|
||||
- 批量修改样式(使用 class)
|
||||
- 使用 `transform` 和 `opacity`(触发合成)
|
||||
- 避免逐帧修改样式(使用 requestAnimationFrame)
|
||||
|
||||
### 3.5 合成层 (Compositing)
|
||||
|
||||
**使用 `will-change` 提示浏览器**:
|
||||
|
||||
```css
|
||||
.animated-element {
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
```
|
||||
|
||||
**使用 GPU 加速**:
|
||||
|
||||
```css
|
||||
.gpu-accelerated {
|
||||
transform: translateZ(0);
|
||||
/* 或 */
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:不要滥用合成层,过多会消耗内存。
|
||||
|
||||
### 3.6 虚拟列表 (Virtual List)
|
||||
|
||||
当需要展示成千上万条数据时(如长列表、聊天记录),如果直接渲染所有 DOM 节点,会导致:
|
||||
|
||||
- **DOM 节点过多**:占用大量内存
|
||||
- **渲染缓慢**:样式计算和布局耗时增加
|
||||
- **滚动卡顿**:浏览器无法维持 60fps
|
||||
|
||||
**解决方案**:只渲染**可视区域**内的元素,加上少量缓冲区。
|
||||
|
||||
<VirtualScrollingDemo />
|
||||
|
||||
**核心原理**:
|
||||
|
||||
1. 计算可视区域能容纳多少个元素。
|
||||
2. 监听滚动事件,根据 `scrollTop` 计算当前应该渲染数据的 `startIndex` 和 `endIndex`。
|
||||
3. 使用 `padding-top` 或 `transform` 将渲染的内容定位到正确位置。
|
||||
**优化原则**:
|
||||
- 尽量避免**重排**(比如不要频繁修改 `width`, `top`)。
|
||||
- 尽量使用只会触发**合成**(Composite)的属性(如 `transform`, `opacity`),这相当于让 GPU(帮厨)来干活,不占用主厨的时间。
|
||||
|
||||
---
|
||||
|
||||
## 4. JavaScript 优化
|
||||
## 3. 进阶:处理海量数据
|
||||
|
||||
JavaScript 是页面的"肌肉",优化它让页面更流畅。
|
||||
如果你的网页需要展示 10,000 条聊天记录,或者 5,000 个商品列表,该怎么办?
|
||||
|
||||
### 3.1 为什么不能直接 `v-for`?
|
||||
|
||||
如果直接在页面上生成 10,000 个 `<div>`,浏览器的内存会瞬间爆炸,渲染树会变得巨大无比,每动一下都会卡死。
|
||||
这就好比餐厅里只有 10 张桌子,你却非要一次性接待 10,000 个客人,结果就是谁也吃不上饭。
|
||||
|
||||
### 3.2 解决方案:虚拟列表 (Virtual Scrolling)
|
||||
|
||||
聪明的工程师想出了**虚拟列表**。
|
||||
它的核心思想是:**欺骗眼睛**。
|
||||
|
||||
既然屏幕只能显示 10 条数据,那我就只渲染这 10 条(加上前后一点缓冲)。当用户滚动时,我快速地把移出屏幕的 DOM 销毁,把新进入屏幕的数据填进去。
|
||||
用户感觉他在滚一个无限长的列表,但实际上浏览器里永远只有几十个 DOM 节点。
|
||||
|
||||
<VirtualScrollingDemo />
|
||||
|
||||
**关键点**:DOM 节点是昂贵的,能省则省。
|
||||
|
||||
---
|
||||
|
||||
## 4. 脚本执行优化 (Script Execution)
|
||||
|
||||
JavaScript 的执行是阻塞主线程的,优化 JS 执行效率对于保持页面流畅至关重要。
|
||||
|
||||
### 4.1 代码压缩 (Minification)
|
||||
|
||||
@@ -470,87 +236,7 @@ async function processLargeArray(items) {
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 图片优化
|
||||
|
||||
图片通常是网页最大的资源,优化图片能显著提升性能。
|
||||
|
||||
### 5.1 格式选择
|
||||
|
||||
<ImageOptimizationDemo />
|
||||
|
||||
**格式对比**:
|
||||
|
||||
| 格式 | 大小 | 质量 | 浏览器支持 | 适用场景 |
|
||||
| ---- | ---- | ---- | ---------- | -------------- |
|
||||
| JPEG | 小 | 好 | 所有 | 照片 |
|
||||
| PNG | 大 | 最好 | 所有 | 透明图片、图标 |
|
||||
| WebP | 很小 | 好 | 现代浏览器 | 大部分场景 |
|
||||
| AVIF | 最小 | 很好 | 最新浏览器 | 追求极致性能 |
|
||||
|
||||
**建议**:
|
||||
|
||||
- 优先使用 WebP
|
||||
- 提供降级方案(JPEG/PNG)
|
||||
|
||||
```html
|
||||
<picture>
|
||||
<source srcset="image.webp" type="image/webp" />
|
||||
<img src="image.jpg" alt="描述" />
|
||||
</picture>
|
||||
```
|
||||
|
||||
### 5.2 响应式图片
|
||||
|
||||
**根据屏幕尺寸加载不同尺寸的图片**:
|
||||
|
||||
```html
|
||||
<img
|
||||
src="image-800.jpg"
|
||||
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
|
||||
sizes="(max-width: 600px) 400px, 800px"
|
||||
alt="响应式图片"
|
||||
/>
|
||||
```
|
||||
|
||||
**解释**:
|
||||
|
||||
- `srcset`:定义不同尺寸的图片
|
||||
- `sizes`:告诉浏览器图片在不同屏幕上的显示尺寸
|
||||
- 浏览器自动选择最合适的图片
|
||||
|
||||
### 5.3 懒加载
|
||||
|
||||
<LazyLoadingDemo />
|
||||
|
||||
**图片懒加载**:只有当图片进入视口时才加载
|
||||
|
||||
**方法 1:使用 `loading` 属性**:
|
||||
|
||||
```html
|
||||
<img src="image.jpg" loading="lazy" alt="懒加载图片" />
|
||||
```
|
||||
|
||||
**方法 2:使用 Intersection Observer**:
|
||||
|
||||
```javascript
|
||||
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)
|
||||
})
|
||||
```
|
||||
|
||||
### 5.4 压缩与裁剪
|
||||
### 5.3 压缩与裁剪
|
||||
|
||||
**使用工具压缩图片**:
|
||||
|
||||
@@ -782,74 +468,39 @@ export default defineConfig({
|
||||
|
||||
## 9. 实战案例
|
||||
|
||||
### 9.1 案例 1:优化一个慢页面
|
||||
### 9.1 案例 1:新闻列表页优化
|
||||
|
||||
**问题**:一个电商商品页加载需要 8 秒
|
||||
**问题**:首屏加载慢,滚动卡顿
|
||||
|
||||
**诊断**:
|
||||
**优化**:
|
||||
|
||||
- 图片总和:3 MB
|
||||
- JavaScript:1.2 MB
|
||||
- CSS:400 KB
|
||||
- 45 个资源请求
|
||||
1. **图片**:WebP + 懒加载
|
||||
2. **列表**:虚拟列表(只渲染可见的 10 项)
|
||||
3. **数据**:分页加载
|
||||
|
||||
**优化措施**:
|
||||
**结果**:LCP 2.5s -> 0.8s
|
||||
|
||||
1. 压缩图片 → 减少 60%(1.2 MB)
|
||||
2. 使用 WebP → 再减少 30%(800 KB)
|
||||
3. 图片懒加载 → 首屏只加载 3 张图
|
||||
4. 代码分割 → 首屏 JS 减少到 300 KB
|
||||
5. 启用 Gzip → CSS 减少到 150 KB
|
||||
### 9.2 案例 2:数据可视化大屏
|
||||
|
||||
**结果**:
|
||||
**问题**:渲染大量节点卡死
|
||||
|
||||
- 首屏时间:8 秒 → 1.8 秒(减少 77%)
|
||||
- Lighthouse 性能评分:35 → 92
|
||||
**优化**:
|
||||
|
||||
### 9.2 案例 2:大型应用的性能优化
|
||||
1. **渲染**:Canvas 代替 DOM
|
||||
2. **计算**:Web Worker 处理数据
|
||||
|
||||
**问题**:单页应用(SPA)首次加载慢
|
||||
**结果**:FPS 10 -> 60
|
||||
|
||||
**优化策略**:
|
||||
### 9.3 案例 3:移动端活动页
|
||||
|
||||
1. **路由懒加载**:每个路由单独打包
|
||||
2. **组件懒加载**:非首屏组件延迟加载
|
||||
3. **虚拟列表**:长列表只渲染可见部分
|
||||
4. **预加载下一页**:用户可能访问的页面预加载
|
||||
5. **SSR(服务端渲染)**:首屏由服务器渲染
|
||||
**问题**:白屏时间长
|
||||
|
||||
**技术选型**:
|
||||
**优化**:
|
||||
|
||||
- 使用 **Vite**(快速构建)
|
||||
- 使用 **Vue 3**(更好的性能)
|
||||
- 使用 **Pinia**(轻量状态管理)
|
||||
- 使用 **Vant**(按需引入的 UI 组件库)
|
||||
1. **资源**:预加载 (Preload) 关键图
|
||||
2. **体验**:骨架屏 (Skeleton)
|
||||
|
||||
**结果**:
|
||||
|
||||
- 首屏加载时间:4.5 秒 → 1.2 秒
|
||||
- Time to Interactive:6 秒 → 1.8 秒
|
||||
|
||||
### 9.3 案例 3:移动端性能优化
|
||||
|
||||
**移动端特殊挑战**:
|
||||
|
||||
- CPU 性能弱
|
||||
- 网络慢
|
||||
- 内存有限
|
||||
|
||||
**优化措施**:
|
||||
|
||||
1. **减少动画**:使用 CSS 动画代替 JS 动画
|
||||
2. **触摸优化**:避免 `click` 延迟,使用 `touchstart`
|
||||
3. **减少重排**:使用 `transform` 代替 `top/left`
|
||||
4. **减少资源**:移动端加载更小的图片
|
||||
5. **PWA**:支持离线访问,提供类原生体验
|
||||
|
||||
**结果**:
|
||||
|
||||
- 移动端评分:45 → 95
|
||||
- 用户留存率提升:+30%
|
||||
**结果**:白屏减少 60%
|
||||
|
||||
---
|
||||
|
||||
@@ -863,69 +514,46 @@ export default defineConfig({
|
||||
- ✅ 使用 CDN 加速静态资源
|
||||
- ✅ 实施代码分割和懒加载
|
||||
- ✅ 压缩和优化图片
|
||||
- ✅ 使用 WebP/AVIF 格式
|
||||
|
||||
**渲染优化**:
|
||||
|
||||
- ✅ 减少重排和重绘
|
||||
- ✅ 使用 CSS 动画(transform、opacity)
|
||||
- ✅ 优化关键渲染路径
|
||||
- ✅ 内联关键 CSS
|
||||
- ✅ 使用 CSS 动画代替 JS 动画
|
||||
|
||||
**JavaScript 优化**:
|
||||
**执行优化**:
|
||||
|
||||
- ✅ 压缩和 Tree Shaking
|
||||
- ✅ 避免长任务(时间切片)
|
||||
- ✅ 使用 Web Workers
|
||||
- ✅ 防抖和节流
|
||||
- ✅ 使用 Web Workers 处理重计算
|
||||
- ✅ 避免长任务(Long Tasks)
|
||||
- ✅ 合理使用防抖和节流
|
||||
|
||||
**缓存优化**:
|
||||
|
||||
- ✅ 配置 HTTP 缓存
|
||||
- ✅ 使用 Service Worker
|
||||
- ✅ 合理使用 LocalStorage
|
||||
- ✅ 配置 HTTP 强缓存和协商缓存
|
||||
- ✅ 考虑使用 Service Worker
|
||||
|
||||
**监控优化**:
|
||||
### 10.2 持续学习
|
||||
|
||||
- ✅ 设置性能预算
|
||||
- ✅ 使用 RUM 和合成监控
|
||||
- ✅ 定期审计性能
|
||||
|
||||
### 10.2 性能优化原则
|
||||
|
||||
1. **测量优先**:先测量,再优化
|
||||
2. **抓大放小**:先优化最大的瓶颈
|
||||
3. **用户体验第一**:关注真实用户感受
|
||||
4. **持续改进**:性能优化是持续的过程
|
||||
5. **团队协作**:让整个团队都关注性能
|
||||
|
||||
### 10.3 常见陷阱
|
||||
|
||||
- ❌ 过早优化:没有测量就开始优化
|
||||
- ❌ 过度优化:为了优化而优化,得不偿失
|
||||
- ❌ 只关注分数:Lighthouse 分数高不代表用户体验好
|
||||
- ❌ 忽视移动端:移动端性能更重要
|
||||
- ❌ 一次性优化:性能需要持续监控和改进
|
||||
|
||||
### 10.4 学习资源
|
||||
|
||||
**工具**:
|
||||
|
||||
- [Lighthouse](https://developers.google.com/web/tools/lighthouse)
|
||||
- [WebPageTest](https://www.webpagetest.org)
|
||||
- [PageSpeed Insights](https://pagespeed.web.dev)
|
||||
|
||||
**文档**:
|
||||
|
||||
- [Web.dev Performance](https://web.dev/performance/)
|
||||
- [MDN Performance](https://developer.mozilla.org/en-US/docs/Web/Performance)
|
||||
|
||||
**书籍**:
|
||||
|
||||
- 《高性能网站建设指南》
|
||||
- 《高性能网站建设进阶指南》
|
||||
- 《Web 性能权威指南》
|
||||
前端性能优化是一个不断发展的领域,新的标准(如 INP)和新的工具(如 Vite, Turbopack)层出不穷。保持好奇心,多看 Performance 面板,是你最好的老师。
|
||||
|
||||
---
|
||||
|
||||
**记住**:性能优化不是炫技,而是为用户创造价值。快的体验就是好的体验。
|
||||
## 11. 名词速查表 (Glossary)
|
||||
|
||||
| 名词 | 全称 | 解释 |
|
||||
| :--- | :--- | :--- |
|
||||
| **FP / FCP** | First Paint / First Contentful Paint | **首屏时间**。用户看到页面第一个像素/第一块内容的时间。 |
|
||||
| **LCP** | Largest Contentful Paint | **最大内容绘制**。页面主要内容加载完成的时间(衡量加载速度的核心指标)。 |
|
||||
| **INP** | Interaction to Next Paint | **交互到下一次绘制**。衡量页面响应速度的新指标(替代 FID),关注点击后的反馈延迟。 |
|
||||
| **CLS** | Cumulative Layout Shift | **累积布局偏移**。页面加载时元素乱跳的程度(衡量视觉稳定性)。 |
|
||||
| **TTFB** | Time to First Byte | **首字节时间**。从发出请求到接收到服务器第一个字节的时间(衡量后端响应速度)。 |
|
||||
| **TBT** | Total Blocking Time | **总阻塞时间**。主线程被长任务阻塞的总时间(衡量页面交互流畅度)。 |
|
||||
| **Reflow** | Reflow (Layout) | **重排**。浏览器重新计算元素位置和大小的过程。成本高,应避免。 |
|
||||
| **Repaint** | Repaint | **重绘**。浏览器重新绘制元素外观(如颜色)的过程。成本中等。 |
|
||||
| **CDN** | Content Delivery Network | **内容分发网络**。把文件存在离用户最近的服务器上,加速下载。 |
|
||||
| **SSR** | Server-Side Rendering | **服务端渲染**。在服务器端生成 HTML,加快首屏显示,利于 SEO。 |
|
||||
| **CSR** | Client-Side Rendering | **客户端渲染**。在浏览器端通过 JS 生成 HTML,交互体验好,但首屏慢。 |
|
||||
| **SSG** | Static Site Generation | **静态站点生成**。构建时生成静态 HTML,访问速度极快。 |
|
||||
| **Tree Shaking** | Tree Shaking | **摇树优化**。构建时移除未使用的代码,减小包体积。 |
|
||||
| **Code Splitting** | Code Splitting | **代码分割**。将代码拆分成小块,按需加载。 |
|
||||
| **Preload / Prefetch** | Preload / Prefetch | **预加载/预获取**。提前告知浏览器加载关键资源或未来可能用到的资源。 |
|
||||
|
||||
Reference in New Issue
Block a user