前缀1. 前端性能优化可以从哪些方面入手?
可以归纳为 5 大方向:
-
加载优化:- 资源合并:合并 CSS、JS 文件,小图标用雪碧图
- 内联资源:关键 CSS 内联,小图可转 base64,
- 懒加载:图片、组件、路由按需加载
- 浏览器缓存策略:减少重复请求
- CDN 加速:静态资源走 CDN
- 使用 HTTP/2:利用多路复用能力
- 优化首屏加载
dns-prefetch--- DNS 预解析preconnect--- 预连接(提前与目标域名完成 DNS 解析 + TCP 握手 + TLS 协商)preload--- 预加载(当前页面必备资源)script的async与defer--- 经典但永远重要
-
渲染优化:优化关键渲染路径、减少重排重绘-
css优化- 选择器优化:避免过深嵌套和复杂选择器
- 压缩 CSS:移除空格、注释、重复规则
- 避免
@import:优先使用link - 清理无用 CSS :如
PurgeCSS - 合理拆分样式,减少首屏阻塞
- 避免触发布局抖动的写法
-
javascript优化- 代码分割:按页面、路由、功能拆包
- 动态导入:按需加载模块
- Tree Shaking:移除未使用代码
- 压缩混淆:降低文件体积
- 使用
async、defer:避免脚本阻塞渲染 - 使用 Web Workers:处理计算密集型任务
- 优化算法和数据结构
- 避免内存泄漏,清理监听器和定时器, 清理闭包
防抖和节流和Web Worker
-
react优化React.memo/PureComponentuseMemo/useCallback- 列表渲染中的稳定 key
- 代码分割与懒加载 ---
React.lazy+import('./')+Suspense - 虚拟列表
- 合理使用 Context 配合 useMemo + useCallback
-
vue优化-
避免将不需要响应的大数据对象用
reactive包裹,可使用shallowRef/shallowReactive跳过深层响应式。 -
对于不变数据用
markRaw永久标记为非响应式 -
计算属性
computed -
v-once:只渲染一次,后续不随响应式数据变化更新,适合纯静态内容。 -
v-memo(Vue 3.2+):类似 React.memo,接收依赖数组,只有依赖变化时才重新渲染。 -
虚拟列表
-
组件缓存 ------
<KeepAlive> -
列表渲染中的 key
-
模板编译优化(Vue 内部,但面试可提及)
- 静态节点提升:模板中的纯静态节点会被提升到渲染函数外,多次渲染复用。
- 预字符串化:大量静态节点会直接编译成字符串通过
innerHTML渲染。 - 动态节点标记与 Block Tree:只追踪可能变化的动态节点,更新时跳过静态内容。
-
非必要的事件监听、定时器、第三方库引用、闭包,防止内存泄漏。
-
-
-
运行时优化:降低主线程压力、优化长列表和复杂计算
-
打包工具优化:
- 入口分割
- 动态导入
import() - 第三方依赖单独拆分
- 路由级分包
Tree Shaking
-
监控与测试:性能监控、性能测试、性能预算
前缀2.: 什么是前端性能优化?为什么重要?
前端性能优化,是指通过技术手段和工程策略,提升网页加载速度、渲染效率与交互流畅度,从而改善用户体验和业务表现的过程。
为什么重要:
- 用户体验:页面越快,用户满意度和留存率越高
- 业务价值:页面加载每变慢 1 秒,转化率可能明显下降
- SEO 影响:搜索引擎会将页面速度作为排名因素之一
- 成本优化:减少带宽消耗,降低服务器压力
前缀3. 前端性能优化的核心指标有哪些?
3.1 Core Web Vitals
LCP(Largest Contentful Paint,最大内容绘制时间):理想值< 2.5sFID(First Input Delay,首次输入延迟):理想值< 100msCLS(Cumulative Layout Shift,累积布局偏移):理想值< 0.1
3.2 其他常见指标
FCP(First Contentful Paint,首次内容绘制)TTI(Time to Interactive,可交互时间)TTFB(Time to First Byte,首字节时间)FPS(页面帧率)- 内存占用、CPU 使用率、错误率
一、加载与网络优化
1.1. 如何减少 HTTP 请求数量?
常见方法:
- 资源合并:合并 CSS、JS 文件,小图标用雪碧图
- 内联资源:关键 CSS 内联,小图可转 base64,
- 懒加载:图片、组件、路由按需加载
- 浏览器缓存策略:减少重复请求
- CDN 加速:静态资源走 CDN
- 使用 HTTP/2:利用多路复用能力
1.2. 什么是浏览器缓存?如何配置?
浏览器缓存是把资源存储在本地,减少重复网络请求的一种机制。
1.2.1 缓存类型
- 强缓存:
Cache-Control、Expires - 协商缓存:
ETag、Last-Modified
1.2.2 常见策略
- 静态资源长期缓存:带 hash 文件名,长缓存
- HTML 文件不做强缓存:避免页面内容更新不及时
- API 接口按业务场景设置短缓存或不缓存
ini
# 静态资源长期缓存
Cache-Control: max-age=31536000, immutable
# HTML 文件不缓存
Cache-Control: no-cache
# API 接口短期缓存
Cache-Control: max-age=300
1.3. CDN 的工作原理和优势是什么?
CDN(内容分发网络)会把资源缓存到各地边缘节点,用户从距离最近的节点获取资源。
优势:
- 降低访问延迟
- 减轻源站压力
- 提高可用性和稳定性
- 节省源站带宽成本
适用场景:
- CSS、JS、图片等静态资源
- 视频、音频、大文件
- 部分可缓存的接口内容
1.4. 什么是 HTTP/2?对性能有什么影响?
HTTP/2 是 HTTP 的升级版本,重点提升传输效率。
主要特性:
- 多路复用:一个连接可并行传输多个请求
- 头部压缩:降低请求头开销
- 二进制分帧:传输更高效
- 服务器推送:可主动推送资源
性能收益:
- 减少连接数
- 降低延迟
- 减少网络开销
- 提升带宽利用率
1.5. 什么是预加载与资源提示?
资源提示是浏览器加载优化的重要手段,用于提前建立连接或提前获取资源。
1.5.1 常见类型
. dns-prefetch --- DNS 预解析
ini
<link rel="dns-prefetch" href="//api.example.com">
作用 :提前完成 DNS 查询,把域名解析成 IP。
当浏览器发现这个标签,就会在空闲时间先对指定域名执行 DNS 解析。后续请求该域名下的资源时,可以省掉 DNS 查询这一 RTT(往返时间),通常能节省 20-120ms。
适用场景:
- 页面上可能很快要请求的第三方域名(CDN、统计、API 服务器等)。
- 不适合滥用:如果域名很多,每个预解析都会消耗一点电量和 CPU,挑重要的 2-3 个即可。
注意事项 :仅解析 DNS,不建立连接。是 preconnect 的轻量版。
1.5.2. preconnect --- 预连接
ini
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
作用 :提前与目标域名完成 DNS 解析 + TCP 握手 + TLS 协商 (HTTPS 情况下)。
比 dns-prefetch 更进一步,直接建立好安全连接。后续请求直接复用这个连接,可以节省 DNS + TCP + TLS 时间(通常 100-300ms)。
适用场景:
- 确定一定会用到的重要第三方资源,如字体文件(Google Fonts)、关键 API、CDN 静态资源。
- 通常配合
crossorigin:如果资源请求需要跨域(如字体需要crossorigin="anonymous"),preconnect也要加上同样的crossorigin属性,否则连接不会复用。
注意:每个连接会占用浏览器和服务器端资源(特别是 HTTP/1.1 只有 6 个并发连接)。只对 2-3 个最重要的域名使用,用完后可能不会立即关闭,保留一段时间,所以要节制。
1.5.3. preload --- 预加载(当前页面必备资源)
ini
<link rel="preload" href="fonts/critical.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="hero.jpg" as="image" media="(min-width: 600px)">
作用 :告诉浏览器:"这个资源 本页马上就需要 ,请以高优先级尽早下载"。
适合那些在正常解析中较晚才会被发现的关键资源(如 CSS 中的字体、首屏大图、JS 动态加载的脚本)。preload 会提升资源的加载优先级,并且不会阻塞 window.onload。
必须设置 as 属性 :明确资源类型(style, script, font, image, fetch 等),否则浏览器无法正确处理优先级与安全策略。
典型使用:
- 字体文件(通常写在 CSS 中,CSS 下载解析后才发请求,太晚了)。
- 首屏大图。
- 动态导入的关键 JavaScript 块。
常见陷阱 :如果 preload 的资源在 3 秒内未被使用(没有匹配的 <script>、<img> 或 CSS 使用),控制台会报警告,且浪费带宽。不要滥用。
1.5.4. prefetch --- 预获取(未来页面可能用)
ini
<link rel="prefetch" href="next-page.js" as="script">
<link rel="prefetch" href="/articles/next.html" as="document">
作用 :以 极低优先级 在浏览器空闲时下载资源到缓存中,为将来导航做准备。
只下载,不解析执行。当用户真的导航到下一页面时,CSS/JS/图片等可以直接从缓存读取,显著加快页面打开速度。
区分于 preload:
preload是告诉浏览器"当前页面马上要",优先级高。prefetch是"下个页面可能用",优先级低,随时可能被中断。
典型场景:单页应用中,对用户可能访问的路由组件进行预获取;电商列表页,对每个商品详情页的 JS/CSS 预获取。
1.5.5. script 的 async 与 defer --- 经典但永远重要
xml
<script src="app.js" defer></script>
<script src="analytics.js" async></script>
defer:异步下载,HTML 解析完后、DOMContentLoaded之前顺序执行。适合依赖 DOM 的脚本。async:异步下载,下载完立即执行,无关顺序。适合独立第三方脚本(统计、广告)
二、CSS 优化
2.1. CSS 性能优化有哪些方法?
常见优化点:
- 选择器优化:避免过深嵌套和复杂选择器
- 压缩 CSS:移除空格、注释、重复规则
- 避免
@import:优先使用link - 清理无用 CSS:如
PurgeCSS - 合理拆分样式,减少首屏阻塞
- 避免触发布局抖动的写法
2.2. 如何优化 CSS 动画性能?
建议:
- 优先使用
transform和opacity - 避免动画作用在
width、height、margin等布局属性上 - 适度使用
will-change - 优先用 CSS 动画,减少 JS 频繁操作 DOM
- 硬件加速要适度,避免显存占用过高
css
.card {
will-change: transform, opacity;
transition: transform 0.3s ease, opacity 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
opacity: 0.95;
}
三、JavaScript 优化
3.1. JavaScript 性能优化策略有哪些?
常见方法:
- 代码分割:按页面、路由、功能拆包
- 动态导入:按需加载模块
- Tree Shaking:移除未使用代码
- 压缩混淆:降低文件体积
- 使用
async、defer:避免脚本阻塞渲染 - 使用 Web Workers:处理计算密集型任务
- 优化算法和数据结构
- 避免内存泄漏,清理监听器和定时器, 清理闭包
- 防抖和节流和
Web Worker
javascript
const loadModule = async () => {
const module = await import('./heavy-module.js');
module.init();
};
3.2. 什么是 Tree Shaking?如何配置?
Tree Shaking 是基于 ES Module 的静态分析能力,移除项目中未被使用的代码。
核心原理:
- 分析依赖关系
- 标记实际使用的导出
- 删除未引用代码
java
// webpack.config.js
module.exports = {
mode: 'production',
optimization: {
usedExports: true,
sideEffects: false
}
};
json
{
"sideEffects": [
"*.css",
"*.scss",
"./src/polyfills.js"
]
}
3.3. 如何实现代码分割(Code Splitting)?
代码分割是把一个大 bundle 拆成多个小 bundle,按需加载。
常见方式:
- 入口分割
- 动态导入
import() - 第三方依赖单独拆分
- 路由级分包
javascript
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
3.4. 如何优化 JavaScript 执行性能?
重点是减少主线程长任务:
- 使用时间切片或
requestIdleCallback - 把大计算放到 Web Worker
- 避免频繁操作 DOM
- 降低重复渲染
- 拆分大型任务,避免页面卡顿
四、图片与资源优化
4.1. 图片优化有哪些技术?
常见方法:
-
格式优化:优先
WebP、AVIF -
尺寸优化:按实际展示尺寸输出
-
响应式图片:使用
srcset -
图片压缩:有损或无损压缩
-
图片懒加载:
-
第一: 使用 html5
loading="lazy"首屏外图片延迟加载 -
第二: Intersection Observer API(推荐)
现代浏览器原生提供的异步观察元素与视口交叉状态的 API,性能优于滚动事件监听。
ini<img class="lazy" data-src="real-image.jpg" src="placeholder.jpg" alt="">iniconst lazyImages = document.querySelectorAll('.lazy'); const observer = new IntersectionObserver((entries, obs) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; // 设置真实图片 img.classList.add('loaded'); obs.unobserve(img); // 加载后停止观察 } }); }, { rootMargin: '0px 0px 200px 0px', // 提前200px开始加载 threshold: 0.01 // 元素露出1%即触发 }); lazyImages.forEach(img => observer.observe(img));
-
-
小图标可考虑雪碧图或 SVG
-
图片异步解码:
decoding="async"告诉浏览器可以在后台异步解码图片,避免解码过程阻塞主线程渲染其他内容 参数:sync:同步解码(默认),可能延迟呈现。async:异步解码,允许先显示其他内容。auto:浏览器决定。
ini
<img
src="small.jpg"
srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 480px, 800px"
loading="lazy"
alt="example"
decoding="async"
/>
4.2. 如何实现资源的预加载和懒加载?
4.2.1 预加载
适用于字体、首屏图片、关键样式、关键脚本等资源。
ini
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<link rel="preload" href="/images/hero.jpg" as="image">
4.2.2 懒加载
适用于图片、组件、列表项、路由页面等非首屏内容。
ini
<img src="/images/demo.jpg" loading="lazy" alt="demo">
ini
const DetailPage = React.lazy(() => import('./DetailPage'));
五、长列表与运行时优化
5.1. 什么是虚拟滚动?如何实现?
虚拟滚动是只渲染可视区域内的列表项,从而减少 DOM 数量、提升长列表性能。
实现原理:
- 计算可视区域可以显示多少项
- 根据滚动位置决定当前需要渲染的区间
- 动态更新列表内容
适用场景:
- 商品列表
- 聊天记录
- 日志表格
- 大数据表单
5.2. 如何优化长列表渲染性能?
常见方法:
- 虚拟滚动
- 分页加载 / 无限滚动
- 滚动事件防抖节流
- 正确使用 key
- 避免在列表项里创建过多内联函数
- 减少不必要的重新渲染
六、离线与应用级优化
6.1. 什么是 Service Worker?如何用于性能优化?
Service Worker 是运行在浏览器后台的脚本,能拦截网络请求,实现缓存和离线能力。
性能优化用途:
- 静态资源缓存
- 离线访问
- 预缓存关键资源
- 缓存优先 / 网络优先等策略切换
ini
self.addEventListener('fetch', event => {
if (event.request.destination === 'image') {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request).then(fetchResponse => {
const responseClone = fetchResponse.clone();
caches.open('images').then(cache => {
cache.put(event.request, responseClone);
});
return fetchResponse;
});
})
);
}
});
6.2. 什么是 PWA?如何提升性能?
PWA(渐进式 Web 应用)结合了 Web 与原生应用的优势。
与性能相关的能力:
- Service Worker 缓存
- App Shell 快速加载
- 预缓存关键资源
- 离线访问
- 后台同步
七、移动端性能优化
7.1. 如何优化移动端性能?
移动端更受网络、CPU、电量和屏幕尺寸影响。
常见优化点:
- 正确设置 viewport
- 优化触摸响应
- 适配弱网环境
- 使用合适图片尺寸和格式
- 减少高耗电、高 CPU 操作
- 控制动画与频繁重绘
ini
<meta name="viewport" content="width=device-width, initial-scale=1.0">
css
.touch-element {
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
八、框架专项优化
React 专项优化
8.1. 避免无意义的渲染 ------ React.memo / PureComponent
- 原理:组件渲染前进行 props 浅比较,无变化则跳过渲染。
- 陷阱 :如果传入了对象、数组、函数等引用类型,父组件每次渲染都会创建新引用,导致浅比较失效。必须配合
useMemo/useCallback稳定引用。 - 面试扩展点 :可以手写
shouldComponentUpdate或自定义比较函数作为第二个参数。
8.2. 缓存计算与回调引用 ------ useMemo / useCallback
useMemo:缓存计算结果,避免每次渲染重复执行昂贵计算,或保持对象/数组引用稳定。useCallback:缓存函数引用,用于传递给已用React.memo的子组件,防止不必要的子渲染。- 原则:不要无差别包裹,因为记忆化本身也有开销。通常在传递引用给子组件,且子组件已优化时才用。
8.3. 列表渲染中的稳定 key
- 为什么不能用
index作为 key:当列表重新排序、增删时,index 会变,导致错误的就地复用、状态错乱或不必要的 DOM 重建。 - 必须使用唯一且稳定的标识符(如数据 ID)。
8.4. 代码分割与懒加载 ------ React.lazy + Suspense
javascript
const Chart = React.lazy(() => import('./Chart'));
<Suspense fallback={<Spinner />}><Chart /></Suspense>
- 将非首屏组件单独打成 chunk,按需加载,减小首屏 JS 体积。
- 可配合
Suspense展示 loading 状态,错误边界处理加载失败。
8.5. 并发特性(React 18)------ 标记非紧急更新
-
useTransition:将某个状态更新标记为低优先级的"过渡",会让出主线程给用户输入等紧急更新。scssconst [isPending, startTransition] = useTransition(); startTransition(() => { setQuery(input); }); -
useDeferredValue:延迟一个值的更新,使 UI 保持响应。 -
面试重点:解释"可中断渲染"的意义,如何解决之前同步渲染导致的长任务掉帧。
8.6. React Fiber 架构 ------ 实现时间切片与优先级调度
- Fiber 将组件树从递归的调用栈转为链表结构的 fiber 节点,渲染可以异步、可中断。
- 工作循环:浏览器空闲时执行一个个小任务(fiber 单元),每执行一段时间检查是否有更高优先级任务插入(如用户点击),若有则暂停,交还主线程。
- 效果:避免了长时间同步渲染阻塞动画/输入。
8.7. 处理长列表 ------ 虚拟列表
- 只渲染可视区域内的元素,大幅减少 DOM 节点。
- 常用库:
react-window、@tanstack/react-virtual。 - 面试常手写简易虚拟列表核心思路:根据容器高度、行高、滚动偏移计算起始索引和结束索引,用
padding或transform撑开列表高度。
8.8. 合理使用 Context,避免不必要的更新
- Context 值变化会导致所有用
useContext的组件重渲染,不管它们是否用到变化的部分。 - 优化:拆分 Context(主题、用户信息分离开),或用
useMemo包裹 value 对象引用,或使用第三方库(如 zustand)进行细粒度订阅。
Vue 性能优化专项
8.1. 利用响应式系统的粒度优化
-
Vue 3 的 Proxy 响应式可以追踪到具体属性变化,组件渲染粒度默认就很细,但也要注意:
- 避免将不需要响应的大数据对象用
reactive包裹,可使用shallowRef/shallowReactive跳过深层响应式。 - 对于不变数据用
markRaw永久标记为非响应式。
- 避免将不需要响应的大数据对象用
8.2. 计算属性 computed 与方法的区别
computed会缓存结果,只有依赖变化才重新计算;methods每次重新渲染都会执行。- 衍生数据必须使用
computed,避免模板内执行开销。
8.3. 组件级别的静态标记与优化
-
v-once:只渲染一次,后续不随响应式数据变化更新,适合纯静态内容。 -
v-memo(Vue 3.2+):类似 React.memo,接收依赖数组,只有依赖变化时才重新渲染。css<div v-memo="[valueA]">{{ expensiveComputation(valueA) }}</div>
8.4. 异步组件与代码分割
javascript
const AsyncComp = defineAsyncComponent(() => import('./Heavy.vue'))
// 带 loading 和 error 处理
const AsyncComp = defineAsyncComponent({
loader: () => import('./Heavy.vue'),
loadingComponent: LoadingComp,
delay: 200,
errorComponent: ErrorComp
})
配合路由懒加载 () => import('./views/About.vue') 分割路由级代码。
8.5. 组件缓存 ------ <KeepAlive>
- 包裹动态组件,保留不活动组件的状态和 DOM,避免反复创建销毁。
- 适用场景:Tab 切换时保持表单填写状态或滚动位置。
8.6. 列表渲染中的 key
- 与 React 同理,必须用唯一的 ID ,不能使用
index,否则列表变动可能导致输入框等状态错乱。
8.7. 模板编译优化(Vue 内部,但面试可提及)
- 静态节点提升:模板中的纯静态节点会被提升到渲染函数外,多次渲染复用。
- 预字符串化:大量静态节点会直接编译成字符串通过
innerHTML渲染。 - 动态节点标记与 Block Tree:只追踪可能变化的动态节点,更新时跳过静态内容。
8.8. 事件与组件销毁清理
- 非必要的事件监听、定时器、第三方库引用在
beforeUnmount/unmounted中清除,防止内存泄漏。
8.9. 虚拟列表
- 与 React 同理,Vue 社区方案:
vue-virtual-scroller,核心原理一致。
九、性能监控与测试
9.1. 什么是 Web Vitals?如何监控?
Web Vitals 是 Google 提出的用户体验指标集合。
核心关注:
LCPFIDCLS
监控方式:
- 使用
web-vitals库采集 - 接入埋点平台进行上报
- 结合真实用户监控(RUM)持续观察
javascript
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
9.2. 如何进行前端性能监控?
可以从 3 类指标入手:
- 加载性能:
FCP、LCP、TTFB、TTI - 运行时性能:FPS、内存、CPU、长任务
- 用户体验:
FID、CLS、错误率
可使用:
Performance Observerweb-vitals- 浏览器 Performance API
- 自研埋点系统
9.3. 如何进行前端性能测试?
常用工具:
- Lighthouse
- WebPageTest
- Chrome DevTools
- GTmetrix
测试建议:
- 建立性能基线
- 在不同网络环境下测试
- 设置性能预算
- 持续跟踪版本变化
ini
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
async function runLighthouse(url) {
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
const options = { logLevel: 'info', output: 'html', port: chrome.port };
const runnerResult = await lighthouse(url, options);
console.log(
'Performance score:',
runnerResult.lhr.categories.performance.score * 100
);
await chrome.kill();
}
10、首屏与渲染优化
10.1. 什么是关键渲染路径?如何优化?
关键渲染路径是浏览器把 HTML、CSS、JavaScript 转换为屏幕像素的过程。
优化目标:
- 减少关键资源数量
- 减少关键资源体积
- 缩短关键路径长度
常见方法:
- 内联首屏关键 CSS
- 异步加载非关键 CSS/JS
- 压缩 HTML、CSS、JS
- 移除未使用代码
- 优化资源加载顺序
xml
<!-- 内联关键 CSS -->
<style>
.header { display: flex; }
</style>
<!-- 异步加载非关键 CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
10.2. 什么是关键 CSS?如何提取和使用?
关键 CSS 指的是首屏渲染必须用到的最小样式集合。
提取方式:
- 工具提取:
Critical、Penthouse - 手动分析首屏模块样式
- 在构建流程中自动化提取
使用方式:
- 首屏关键 CSS 内联
- 完整 CSS 异步加载
xml
<style>
.header { display: flex; height: 60px; }
.hero { min-height: 400px; }
</style>
<link rel="preload" href="/styles/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
10.3. 如何优化首屏加载时间?
常见策略:
- 关键资源优先加载
- 首屏关键 CSS 内联
- 代码分割,只加载首页需要的代码
- 使用 SSR 或 SSG,减少首屏等待
- 使用骨架屏提升感知速度
- 预加载首屏关键图片、字体、样式
javascript
const HomePage = lazy(() => import('./HomePage'));
const ProductPage = lazy(() => import('./ProductPage'));
function App() {
return (
<Suspense fallback={<SkeletonLoader />}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/product" element={<ProductPage />} />
</Routes>
</Suspense>
);
}
十一、前端性能优化最佳实践总结
11. 前端性能优化最佳实践
11.1 加载优化
- 减少 HTTP 请求数量
- 启用 Gzip / Brotli 压缩
- 使用 CDN
- 配置合理缓存策略
- 优化关键渲染路径
- 提前加载关键资源
11.2 渲染优化
- 提取关键 CSS
- 减少阻塞渲染资源
- 避免频繁重排重绘
- 优化动画属性使用
11.3 JavaScript 优化
- 代码分割与懒加载
- Tree Shaking
- 避免长任务阻塞主线程
- 使用 Web Workers 处理重计算
- 及时清理事件和定时器
11.4 列表与交互优化
- 长列表使用虚拟滚动
- 滚动事件防抖节流
- 避免不必要的重复渲染
11.5 图片与静态资源优化
- 使用现代图片格式
- 控制资源体积
- 按需加载非首屏资源
- 优化字体加载策略
11.6 监控与工程化
-
建立性能监控体系
-
设置性能预算
-
定期进行性能测试
-
持续关注 Core Web Vitals
-
在开发流程中贯彻性能优先理念