[超详细,推荐!!!]前端性能优化策略详解

news2025/5/12 21:09:59

学习记录,部分内容版权归@妙码学院

1.优化内容包括那些

其实前端的优化,整体粗略概括下来,白话之:

  1. 打开速度怎么变快
  2. 再次打开速度怎么变快
  3. 操作怎么才顺滑
  4. 动画怎么保证流畅

2.性能优化

2.1首屏加载优化

在了解优化方法和策略之前,先了解一下首屏加载的量化指标有哪些:

指标

性能指标

前端新能指标和与优化策略
在这里插入图片描述
在这里插入图片描述

  • 白屏时间​​:从输入URL到FP的时间段,受网络链路(DNS/TCP)和主文档加载影响。
  • ​​测量工具​​:可通过performance.getEntriesByName(‘first-paint’)获取FP/FCP数据,LCP需结合浏览器API(如PerformanceObserver)或工具库(如web-vitals)

策略
在这里插入图片描述

减少首屏加载资源体积(优化策略)
一、加载阶段优化

目标:缩短网络请求时间,加速资源下载,直接影响 TTFB、FP、FCP
核心逻辑:减少首屏资源体积 → 减少传输时间 → 更快启动渲染

1. 网络传输优化

CDN加速

  • 将静态资源(图片、CSS/JS、字体)部署到全球CDN节点,缩短资源传输距离,降低TTFB。

启用Gzip/Brotli压缩

  • 对文本类资源(HTML/CSS/JS)压缩,体积减少60%以上,降低传输耗时。
2. 资源体积控制

优化图片

  • 使用WebP格式(比JPEG体积小30%)、压缩图片(ImageOptim)、按需裁剪尺寸。

字体子集化

  • 通过Fontmin提取页面实际使用的字符,减少字体文件体积(如从2MB降至50KB)。

移除冗余第三方库

  • 分析依赖,替换臃肿库(如全量Lodash → 按需加载),减少JS体积。

3. 请求数量优化

  • 合并CSS/JS文件

    减少HTTP请求次数(如将10个小文件合并为1个),降低网络开销。


二、渲染阶段优化

目标:加速首屏内容渲染,保障视觉稳定性,直接影响 LCP、CLS
核心逻辑:优先渲染关键内容 → 快速达到可交互状态 → 避免布局偏移

1. 关键资源优先级

动态加载非关键CSS/JS

  • 通过<link rel="preload">预加载首屏资源,延迟非关键脚本(如广告、分析SDK)。

服务端渲染(SSR)与静态生成(SSG)

  • 使用Next.js/Nuxt.js在服务端生成完整HTML,减少客户端渲染耗时,直接输出可见内容。
2. 按需加载策略

懒加载非首屏资源

  • 图片/视频添加loading="lazy"属性,仅当用户滚动到可视区域时加载。

3. 视觉稳定性保障
预定义尺寸占位

  • 为图片/视频设置width/height属性,或使用CSS宽高比容器,避免布局抖动(CLS优化)。

  • 隐含优化项(图片中未明确,但属于CLS优化范畴)


三、跨阶段优化

目标:贯穿加载和渲染阶段,提升整体性能

1. 浏览器缓存策略

  • 配置Cache-ControlETag,复用已缓存资源(如字体、JS库),减少重复请求。

2. 代码执行效率

Tree Shaking与代码拆分

  • 移除未使用的代码(Webpack/Rollup),按路由拆分JS包,减少主线程阻塞时间(TBT优化)。

四、优化措施与性能指标关联表
优化措施影响阶段关联指标具体收益案例
CDN加速加载阶段TTFB、FCP图片加载时间从800ms降至300ms
字体子集化加载阶段FCP字体文件体积减少95%
服务端渲染(SSR)渲染阶段LCPLCP从3.2s优化至1.8s
懒加载图片渲染阶段LCP、CLSCLS分数从0.25降至0.05
移除冗余库加载阶段TTFB、FCP、TBTJS体积减少40%,主线程阻塞减少50%

预加载(优化策略)

一、预加载关键资源

原理
通过<link rel="preload">提前加载首屏必需资源(CSS、JS、字体),减少资源加载与渲染的阻塞时间,提升FCP(首次内容渲染)和LCP(最大内容渲染)指标。

代码示例

<!-- 预加载CSS文件 -->
<link rel="preload" href="style/main.css" as="style">
<!-- 预加载JS文件(需注意跨域资源的`crossorigin`属性) -->
<link rel="preload" href="javascript/main.js" as="script">
<!-- 预加载字体文件(需指定类型和跨域) -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

注意事项

  1. as属性必须正确:告知浏览器资源类型(如stylescriptfont),否则可能重复下载。
  2. 字体跨域问题:若字体托管在CDN,需添加crossorigin属性。
  3. 兼容性:支持Chrome/Firefox/Edge,Safari部分支持。

优化效果验证
使用Chrome DevTools的 Network面板,观察资源加载优先级是否从Low提升至High


二、嵌入关键CSS

原理
将首屏渲染所需CSS直接内联到HTML的<style>标签中,避免外链CSS文件请求阻塞渲染,直接优化FP(首次绘制)和FCP。

代码示例

<head>
  <style>
    /* 关键CSS:首屏可见元素的样式 */
    .header, .hero-image { 
      display: block; 
      width: 100%;
    }
  </style>
  <!-- 非关键CSS异步加载 -->
  <link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
</head>

最佳实践

  1. 提取关键CSS:使用工具(如Critical、Penthouse)自动提取首屏样式。
  2. 非关键CSS异步加载:通过media="print"+onload切换媒体类型,避免阻塞。

优化效果验证
Lighthouse的 CSS Delivery Audit 会提示未内联的关键CSS文件。


三、异步加载JavaScript

原理
通过asyncdefer属性控制脚本加载与执行时机,减少JS阻塞主线程,优化LCP和TTI(可交互时间)。

代码示例

<!-- 异步加载:下载不阻塞,执行时机不确定 -->
<script src="analytics.js" async></script>
<!-- 延迟执行:下载不阻塞,在DOM解析完成后按顺序执行 -->
<script src="main.js" defer></script>

对比与选择

属性执行时机适用场景
async下载完成后立即执行(无序)独立脚本(如统计代码)
deferDOM解析完成后顺序执行依赖DOM或需要顺序执行的脚本

优化效果验证
Chrome DevTools的 Performance面板 查看主线程阻塞时间(Total Blocking Time)。


四、预加载字体与关键图片

原理
预加载首屏字体和图片,避免FOIT(字体未加载时的文本隐藏)和布局抖动,优化CLS(累积布局偏移)。

代码示例

<!-- 预加载首屏图片 -->
<link rel="preload" href="hero-image.webp" as="image" imagesrcset="hero-1x.webp 1x, hero-2x.webp 2x">
<!-- 预加载字体 -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

注意事项

  1. 响应式图片优化:结合imagesrcset适配不同分辨率。
  2. 字体加载兜底:使用font-display: swap显示备用字体,避免FOIT。

优化效果验证
Web Vitals监控工具查看CLS分数变化,目标小于0.1。


五、HTTP/2 Server Push

原理
服务器在响应HTML请求时,主动推送关键资源(CSS、JS),减少往返请求次数,优化TTFB(首字节时间)和FCP。

配置示例(Nginx)

server {
  listen 443 ssl http2;
  # 推送主CSS文件
  location = /index.html {
    http2_push /style/main.css;
    http2_push /javascript/main.js;
  }
}

最佳实践

  1. 避免过度推送:仅推送首屏必需资源,防止带宽浪费。
  2. 缓存策略:推送资源需设置有效缓存头,避免重复传输。

优化效果验证
Chrome DevTools的 Network面板 检查资源是否通过h2协议推送(Size列显示Push)。


在这里插入图片描述

预渲染(优化策略)

在这里插入图片描述

2.2 动画卡顿优化(最熟悉)

从浏览器底层原理简述


动画卡顿优化深度解析
动画流畅性是用户体验的核心指标之一,直接影响用户对产品“流畅度”的感知。本文基于图片中的优化措施,从原理、实践到工具验证进行全面拆解。


1. 减少主线程阻塞

原理
浏览器主线程负责执行 JavaScript、样式计算、布局(Layout)、绘制(Paint)等任务。若主线程被长任务(Long Tasks,>50ms)阻塞,会导致动画帧无法按时渲染,引发卡顿。

优化方法

• 拆分长任务

将复杂逻辑拆分为多个微任务(setTimeoutqueueMicrotask),每段执行时间控制在5ms以内。

function processChunk() {
  // 每批次处理100条数据
  for (let i = 0; i < 100; i++) { /* ... */ }
  if (hasMore) setTimeout(processChunk, 0);
}
• Web Worker 异步处理

将耗时计算(如物理引擎、图像处理)移至 Worker 线程:

// 主线程
const worker = new Worker('calc.js');
worker.postMessage(data);
worker.onmessage = (e) => { updateUI(e.data); };

// calc.js(Worker线程)
self.onmessage = (e) => { 
  const result = heavyCompute(e.data); 
  self.postMessage(result);
};

验证工具
• Chrome DevTools - Performance 面板:分析任务耗时和长任务分布。

• Long Tasks API:通过PerformanceObserver监听长任务。


2. GPU 加速

原理
现代浏览器通过合成层(Compositing Layer)优化渲染:将特定元素提升为独立层,由 GPU 直接处理变换(Transform)和透明度(Opacity),跳过重排(Reflow)和重绘(Repaint)。

优化方法

• 优先使用 GPU 友好属性
.box {
  /* ✅ 触发合成层(GPU加速) */
  transform: translateZ(0); 
  opacity: 0.9;
  /* ❌ 避免触发重排 */
  left: 100px; 
  top: 200px;
}
• 优化动画触发条件

• 对静态元素使用will-change: transform预提示浏览器。

• 避免在滚动时频繁修改非 GPU 属性(如width)。

注意事项
• 过度使用合成层会增加内存占用(每层约 4MB),需通过 Layers 面板监控层数量。

• 使用transform: translate3d()替代translate()强制开启 GPU 加速。


3. 维持 60 FPS 帧率

原理
浏览器默认以 60Hz 刷新率渲染(每帧 16.67ms),若单帧渲染时间超过此阈值,会导致帧率下降。

优化方法

• 使用 requestAnimationFrame

替代setTimeout/setInterval,确保动画与浏览器刷新率同步:

function animate() {
  element.style.transform = `translateX(${pos}px)`;
  pos += 1;
  requestAnimationFrame(animate);
}
• 限制计算复杂度

• 避免在动画回调中执行 DOM 查询(如offsetWidth),触发强制同步布局(Forced Synchronous Layout)。

• 对复杂计算使用缓存或预计算。

验证工具
• Chrome DevTools - FPS Meter:实时监控帧率波动。

console.time/console.timeEnd:测量单帧耗时。


4. 压缩动画帧渲染时间

原理
每帧的渲染流程包括:JavaScript → 样式计算 → 布局 → 绘制 → 合成。需减少各阶段耗时。

优化方法

• 简化样式计算

减少 CSS 选择器复杂度(如避免div:nth-child(3) > a:hover)。
• 减少布局抖动(Layout Thrashing)

// ❌ 错误:多次读取/写入布局属性
const width = element.offsetWidth;
element.style.height = width + 'px'; 
const height = element.offsetHeight;

// ✅ 正确:批量读取后写入
const width = element.offsetWidth;
const height = width * 0.75;
element.style.height = height + 'px';
• 使用 CSS 动画替代 JS 动画

CSS 动画由合成线程处理,不受主线程阻塞影响:

@keyframes slide {
  from { transform: translateX(0); }
  to { transform: translateX(100px); }
}
.box { animation: slide 1s ease-in-out; }

5. 节流(Throttle)与防抖(Debounce)

原理
高频事件(如滚动、窗口调整)频繁触发回调会导致性能问题。
• 节流:固定时间间隔内只执行一次(如每秒 10 次)。

• 防抖:事件停止触发后延迟执行(如输入框停止输入 300ms 后搜索)。

代码示例

// 节流
function throttle(fn, delay) {
  let lastTime = 0;
  return (...args) => {
    const now = Date.now();
    if (now - lastTime >= delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

// 防抖
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 应用:滚动事件节流
window.addEventListener('scroll', throttle(updatePosition, 100));

总结与工具链

优化方向关键工具验证指标
主线程任务拆分Chrome Performance 面板Long Tasks < 50ms
GPU 加速Layers 面板、CSS Triggers 网站合成层数量 < 30
帧率稳定性FPS Meter、requestAnimationFrame60 FPS ±5%
高频事件控制console.time、事件监听分析回调执行频率 ≤ 屏幕刷新率

通过综合应用上述策略,可显著提升动画流畅性。建议结合 Web Vitals 和 Lighthouse 持续监控性能表现。

2.3 应用状态管理优化

在这里插入图片描述

2.4 应用视图层更新优化

React 视图更新优化详解

在这里插入图片描述

1. 使用 React.memo 防止不必要的重新渲染

原理
React.memo 是一个高阶组件(HOC),用于包裹函数组件,通过浅层对比组件的 props 变化,仅在 props 发生变更时触发重新渲染。避免父组件状态更新导致子组件无意义的重绘。

适用场景
• 子组件依赖父组件传递的 props,且子组件渲染成本较高(如复杂计算或 DOM 操作)。

• 当父组件频繁更新但子组件的 props 未变化时。

代码示例

const MyComponent = React.memo(({ data }) => {
  return <div>{data}</div>;
});

// 父组件
const Parent = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      <button onClick={() => setCount(c => c + 1)}>Click {count}</button>
      <MyComponent data="静态数据" /> {/* 不随 count 变化重新渲染 */}
    </>
  );
};

注意事项
• 若 props 包含对象或函数,需确保它们的引用稳定(结合 useMemo/useCallback)。

• 深比较场景需自定义对比函数:

React.memo(MyComponent, (prevProps, nextProps) => {
  return prevProps.data.id === nextProps.data.id;
});

2. 使用 useMemouseCallback 缓存结果

原理
useMemo:缓存复杂计算结果,仅在依赖项变化时重新计算。

useCallback:缓存函数实例,避免因函数引用变化触发子组件重渲染。

适用场景
• 计算密集型操作(如数据转换、过滤)。

• 需要稳定函数引用的场景(如事件处理函数传递给子组件)。

代码示例

const List = ({ items }) => {
  const filteredItems = useMemo(() => {
    return items.filter(item => item.value > 100); // 依赖 items 变化
  }, [items]);

  const handleClick = useCallback(() => {
    console.log('点击事件'); // 依赖项为空,函数引用不变
  }, []);

  return <Child items={filteredItems} onClick={handleClick} />;
};

最佳实践
• 避免滥用:仅在计算成本高或引用稳定性关键时使用。

• 依赖项需明确,避免遗漏导致缓存失效。


3. 拆分组件

原理
将大型组件拆分为更小的独立组件,利用 React 的局部更新机制,仅重新渲染变更部分的子树。

适用场景
• 页面中存在独立功能区块(如导航栏、侧边栏、内容区)。

• 动态数据和静态数据混合的场景。

示例

// 原始组件
const UserProfile = ({ user }) => (
  <div>
    <Header avatar={user.avatar} />
    <Content posts={user.posts} />
    <Footer />
  </div>
);

// 拆分后:Header、Content、Footer 独立更新
const Header = React.memo(({ avatar }) => <div>{avatar}</div>);
const Content = ({ posts }) => posts.map(post => <PostItem key={post.id} post={post} />);

优化效果
• 父组件状态变化时,未受影响的子组件不重新渲染。

• 结合 React.memo 效果更佳。


4. 虚拟滚动(Virtualized List)

原理
仅渲染可视区域内的列表项,动态加载和卸载元素,减少 DOM 节点数量和渲染压力。

适用场景
• 长列表(如 1000+ 项)的渲染性能优化。

• 移动端或低性能设备。

实现库
• react-virtualized:经典方案,支持多种布局。

• react-window:轻量级替代,更小的包体积。

代码示例(react-window)

import { FixedSizeList as List } from 'react-window';

const Row = ({ index, style }) => (
  <div style={style}>Row {index}</div>
);

const VirtualList = () => (
  <List height={600} itemCount={1000} itemSize={35} width={300}>
    {Row}
  </List>
);

核心参数
itemCount:总项数

itemSize:每项高度(固定或动态)

overscanCount:预渲染项数(减少滚动白屏)


5. 批处理更新(Batching Updates)

原理
将多个状态更新合并为一次渲染,减少重复的渲染周期。React 18+ 默认在异步回调(如 Promise、setTimeout)中启用自动批处理。

适用场景
• 多个连续状态变更(如表单字段更新、批量数据加载)。

代码示例

// React 17 及以下需手动批处理
const handleClick = () => {
  ReactDOM.unstable_batchedUpdates(() => {
    setCount(c => c + 1);
    setName('New Name');
  });
};

// React 18+ 自动批处理(无需额外操作)
fetchData().then(() => {
  setData(data);
  setLoading(false); // 一次渲染完成
});

优化效果
• 减少不必要的渲染次数,提升整体性能。


Vue 视图更新优化详解

在这里插入图片描述

1. 避免多余的响应式数据

原理
Vue 的响应式系统(reactive/ref)会追踪数据变化并触发更新。非响应式数据(如静态配置)若错误包裹为响应式,会增加内存和计算开销。

适用场景
• 静态配置、常量或无需追踪变化的临时变量。

代码示例

<script setup>
// 错误:静态数据使用响应式
const staticData = reactive({ title: '标题' }); 

// 正确:直接使用普通对象
const staticData = { title: '标题' };
</script>

最佳实践
• 使用 Object.freeze() 冻结静态对象,避免误修改。

• 仅对需要动态更新的数据使用 refreactive


2. 使用 v-oncev-memo

原理
v-once:渲染元素一次,后续跳过更新。

v-memo:根据依赖项缓存模板片段,仅当依赖变化时重新渲染。

适用场景
v-once:静态内容(如页脚版权信息)。

v-memo:高频更新但部分依赖稳定的组件。

代码示例

<template>
  <!-- 静态内容 -->
  <div v-once>{{ staticText }}</div>

  <!-- 根据 id 缓存列表项 -->
  <div v-for="item in list" :key="item.id" v-memo="[item.id]">
    {{ item.name }}
  </div>
</template>

注意事项
v-memo 需与 v-for 结合使用,依赖项需包含唯一标识(如 id)。


3. 拆分组件与 keep-alive 缓存

原理
• 拆分组件:将大型组件拆分为子组件,利用 Vue 的局部更新机制。

keep-alive:缓存非活跃组件实例,避免重复渲染(如 Tab 切换)。

代码示例

<template>
  <!-- 缓存动态组件 -->
  <keep-alive>
    <component :is="currentTabComponent"></component>
  </keep-alive>
</template>

<script setup>
// 子组件:仅当 props 变化时更新
const ChildComponent = defineComponent({
  props: ['data'],
  setup(props) {
    // 逻辑
  }
});
</script>

优化效果
• 减少父组件更新对子组件的影响。

keep-alive 避免重复执行生命周期钩子(如 mounted)。


4. 避免 watch 的过度使用

原理
watch 监听数据变化并触发回调,过度使用会增加计算开销。

优化策略
• 精确监听必要依赖,避免监听整个对象。

• 使用 watchEffect 自动追踪依赖,简化代码。

代码示例

<script setup>
// 错误:监听整个对象
watch(
  () => state.user,
  (newVal) => { /* ... */ },
  { deep: true } // 深度监听开销大
);

// 正确:仅监听必要字段
watch(
  () => state.user.id,
  (newId) => { /* ... */ }
);

// 使用 watchEffect 自动追踪
watchEffect(() => {
  console.log('用户ID变化:', state.user.id);
});
</script>

注意事项
• 避免在 watch 中执行高耗时操作。

• 使用 { immediate: true } 时需注意初始触发逻辑。


5. 虚拟滚动优化长列表

原理
与 React 类似,仅渲染可视区域内容,减少 DOM 节点数量。

实现库
• vue-virtual-scroller:Vue 生态主流方案。

• vue3-virtual-list:轻量级替代。

代码示例(vue-virtual-scroller)

<template>
  <RecycleScroller
    class="scroller"
    :items="list"
    :item-size="32"
    key-field="id"
  >
    <template #default="{ item }">
      <div>{{ item.name }}</div>
    </template>
  </RecycleScroller>
</template>

<script setup>
import { RecycleScroller } from 'vue-virtual-scroller';
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
</script>

核心参数
items:数据源

item-size:每项高度

page-mode:启用滚动容器优化


总结

React 优化核心:利用 memo 和缓存 Hook 减少渲染,拆分组件隔离变更,虚拟滚动解决长列表性能问题。
Vue优化核心:精准控制响应式数据,通过指令缓存模板,合理使用组件缓存和虚拟滚动。

事件和渲染细节优化

在这里插入图片描述


前端事件与渲染优化详解
从高频事件处理、DOM操作优化到资源加载策略,系统解析性能优化方法:


1. 节流(Throttle)与防抖(Debounce)

核心问题:高频事件(如滚动、输入)频繁触发回调,导致主线程阻塞、页面卡顿。

防抖(Debounce)
• 定义:事件停止触发后延迟执行回调(如输入框停止输入 300ms 后搜索)。

• 代码修正与注释:

const debounce = (func, delay) => {
  let timeout;  // 存储定时器ID
  return (...args) => {
    clearTimeout(timeout);  // 清除上一次的定时器
    timeout = setTimeout(() => func(...args), delay);  // 重新计时
  };
};

// 使用示例:输入框搜索
const handleInput = debounce((value) => {
  console.log('搜索关键词:', value);  // 实际调用API的代码
}, 300);

inputElement.addEventListener('input', (e) => handleInput(e.target.value));

节流(Throttle)
• 定义:固定时间间隔内只执行一次回调(如滚动事件每 100ms 触发一次)。

• 代码示例:

const throttle = (func, interval) => {
  let lastTime = 0;
  return (...args) => {
    const now = Date.now();
    if (now - lastTime >= interval) {  // 超过间隔时间才执行
      func(...args);
      lastTime = now;
    }
  };
};

// 使用示例:滚动事件监听
window.addEventListener('scroll', throttle(() => {
  console.log('滚动位置:', window.scrollY);
}, 100));

适用场景对比

策略适用场景典型案例
防抖输入验证、搜索联想输入框停止输入后触发搜索
节流滚动加载、窗口调整无限滚动列表的分批加载

2. 事件绑定优化

Vue 中的事件绑定
.native 修饰符:用于监听组件根元素的原生 DOM 事件。

<!-- 父组件监听子组件的原生 click 事件 -->
<Child @click.native="handleChildClick" />

• 注意:Vue 3 已弃用 .native,改为 emits 显式声明事件。

React 中的事件绑定

• 避免过多回调传递:

• 问题:在深层子组件中传递回调函数,易导致不必要的重渲染。

• 优化:使用 Context API 或状态管理库(如 Redux)共享回调。

// 错误:每层传递回调
<GrandChild onClick={handleClick} />

// 正确:通过 Context 共享
const ClickContext = createContext();
<ClickContext.Provider value={handleClick}>
  <GrandChild />
</ClickContext.Provider>

3. 避免不必要的 DOM 操作

问题根源
• DOM 操作成本高:浏览器重排(Reflow)和重绘(Repaint)消耗大量性能。

• 典型案例:循环中直接操作 DOM,导致多次渲染。

优化方法

  1. 批量更新:使用文档片段(DocumentFragment)合并多次操作。

    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 1000; i++) {
      const div = document.createElement('div');
      fragment.appendChild(div);
    }
    document.body.appendChild(fragment);  // 仅触发一次重排
    
  2. 虚拟 DOM 优势:React/Vue 通过 Diff 算法最小化真实 DOM 操作。


4. 异步加载与懒加载

资源懒加载
• 图片懒加载:仅加载可视区域内的图片。

<!-- 使用 loading="lazy"(原生支持) -->
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy" />

<!-- 或通过 Intersection Observer API 实现 -->
<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>

路由组件懒加载
• React:使用 React.lazy + Suspense

const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Route path="/home" component={Home} />
      <Route path="/about" component={About} />
    </Suspense>
  );
}

• Vue:动态导入组件。

<script setup>
const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'));
</script>

5. 请求合并

网络请求优化
• 防抖处理:高频触发的请求合并为一次(如搜索联想)。

const search = debounce((keyword) => {
  fetch(`/api/search?q=${keyword}`).then(/* ... */);
}, 300);

• 批量接口设计:后端提供批量处理接口,减少请求次数。

// 单次请求:多次调用
fetch('/api/user/1');
fetch('/api/user/2');

// 合并请求:一次调用
fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ ids: [1, 2] })
});

总结与工具推荐

优化方向推荐工具/库验证指标
防抖/节流Lodash 的 debounce/throttle主线程阻塞时间(Performance 面板)
懒加载react-lazyloadvue-lazyloadLCP、FCP
请求合并Axios 拦截器、GraphQL 批量查询网络请求数量(Network 面板)

通过综合应用上述策略,可显著提升页面响应速度与用户体验。建议结合 Lighthouse 和 Web Vitals 持续监控优化效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据提取之BeautifulSoup4快速使用

文章目录 一、前言二、概述2.1 安装2.2 初始化2.3 对象类型 三、遍历文档树3.1 子节点3.2 父节点3.3 兄弟节点3.4 前后节点3.5 节点内容3.5.1 文本内容3.5.2 属性值3.5.3 标签删除 四、搜索文档树4.1 find_all4.2 find4.3 CSS选择器4.4 更多 一、前言 官方文档&#xff1a;http…

list类的详细讲解

【本节目标】 1. list的介绍及使用 2. list的深度剖析及模拟实现 3. list与vector的对比 1. list的介绍及使用 1.1 list的介绍 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list 的底层是双向链表结构&a…

Linux系统下安装mongodb

1. 配置MongoDB的yum仓库 创建仓库文件 sudo vi /etc/yum.repos.d/mongodb-org.repo添加仓库配置 根据系统版本选择配置&#xff08;以下示例为CentOS 7和CentOS 9的配置&#xff09;&#xff1a; CentOS 7&#xff08;安装MongoDB 5.0/4.2等旧版本&#xff09;&#xff1a; In…

kuka, fanuc, abb机器人和移动相机的标定

基础知识 : 一, 9点标定之固定相机标定: 图1: 固定位置相机拍照 因为相机和机器人的基坐标系是固定的, 所以在海康威视相机的9点标定功能栏中, 填上海康使用“圆查找”捕捉到的坐标值, 再将机器人显示的工具坐标系在基坐标系的实时位置pos_act值填入物理坐标X, Y中即可 图2:…

Android Framework学习四:init进程实现

文章目录 init流程简介init源码执行顺序执行顺序 init进程的具体工作事项挂载文件系统设置 SELinuxSecondStageMaininit.rc启动zygote和serviceManager进程的重要性serviceManager工作原理 Framework学习之系列文章 init流程简介 下面图片主要围绕 Android 系统中init进程的运…

Java引用RabbitMQ快速入门

这里写目录 Java发送消息给MQ消费者接收消息实现一个队列绑定多个消费者消息推送限制 Fanout交换机路由的作用Direct交换机使用案例 Topic交换机声明队列和交换机的方式MQ消息转换器业务改造生产者可靠性设置重连 系统可靠性 Java发送消息给MQ public void testSendMessage() t…

用R语言+随机森林玩转遥感空间预测-基于R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析

遥感数据具有高维度、非线性及空间异质性等特点&#xff0c;传统分析方法往往难以充分挖掘其信息价值。机器学习技术的引入为遥感数据处理与模型预测提供了新的解决方案&#xff0c;其中随机森林&#xff08;Random Forest&#xff09;以其优异的性能和灵活性成为研究者的首选工…

Spring Boot 文件上传实现详解

在项目开发过程中&#xff0c;文件上传是极为常见的功能需求。对于熟悉 Spring MVC 文件上传操作的开发者而言&#xff0c;Spring Boot 中的文件上传与之原理基本相通&#xff0c;只是在依赖管理和配置方式上更为简化。接下来&#xff0c;将详细阐述 Spring Boot 项目中文件上传…

查看单元测试覆盖率

文章目录 1、POM文件配置2、编写单元测试3、执行单元测试4、查看单元测试覆盖率 1、POM文件配置 pom文件配置jacoco插件 <!-- 生成JaCoCo覆盖率数据插件 --> <plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artif…

基于SpringBoot的在线教育管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

C# 方法(方法重载)

本章内容: 方法的结构 方法体内部的代码执行 局部变量 局部常量 控制流 方法调用 返回值 返回语句和void方法 局部函数 参数 值参数 引用参数 引用类型作为值参数和引用参数 输出参数 参数数组 参数类型总结 方法重载 命名参数 可选参数 栈帧 递归 方法重载 一个类中可以有多个…

3、食品包装控制系统 - /自动化与控制组件/food-packaging-control

76个工业组件库示例汇总 食品包装线控制系统 这是一个用于食品包装线控制系统的自定义组件&#xff0c;提供了食品包装生产线的可视化监控与控制界面。组件采用工业风格设计&#xff0c;包含生产流程控制、实时数据监控和逻辑编程三个主要功能区域。 功能特点 工业风格UI设…

初始图形学(7)

上一章完成了相机类的实现&#xff0c;对之前所学的内容进行了封装与整理&#xff0c;现在要学习新的内容。 抗锯齿 我们放大之前渲染的图片&#xff0c;往往会发现我们渲染的图像边缘有尖锐的"阶梯"性质。这种阶梯状被称为"锯齿"。当真实的相机拍照时&a…

线程的一些事(2)

在java中&#xff0c;线程的终止&#xff0c;是一种“软性”操作&#xff0c;必须要对应的线程配合&#xff0c;才能把终止落实下去 然而&#xff0c;系统原生的api其实还提供了&#xff0c;强制终止线程的操作&#xff0c;无论线程执行到哪&#xff0c;都能强行把这个线程干掉…

使用lldb看看Rust的HashMap

目录 前言 正文 读取桶的状态 获取键值对 键值对的指针地址 此时&#xff0c;读取数据 读取索引4的键值对 多添加几个键值对 使用i32作为键&#xff0c;&str作为值 使用i32作为键&#xff0c;String作为值 前言 前面使用ldb看了看不同的类型&#xff0c;这篇再使用…

2025最新免费视频号下载工具!支持Win/Mac,一键解析原画质+封面

软件介绍 适用于Windows 2025 最新5月蝴蝶视频号下载工具&#xff0c;免费使用&#xff0c;无广告且免费&#xff0c;支持对原视频和封面进行解析下载&#xff0c;亲测可用&#xff0c;现在很多工具都失效了&#xff0c;难得的几款下载视频号工具&#xff0c;大家且用且珍…

Newton GPU 机器人仿真器入门教程(零)— NVIDIA、DeepMind、Disney 联合推出

系列文章目录 目录 系列文章目录 前言 一、快速入门 1.1 实时渲染 1.2 USD 渲染 1.3 示例&#xff1a;创建一个粒子链 二、重要概念 三、API 参考 3.1 求解器 3.1.1 XPBD 求解器 3.1.2 VBD 求解器 3.1.3 MuJoCo 求解器 3.2 关节控制模式 四、Newton 集成 4.1 Is…

【C++】学习、项目时Debug总结

这里写目录标题 1. 内存问题1.1. 内存泄漏1.1.1. 内存泄漏案例检查方法1.1.2. 主线程提前退出导致【控】1.1.3. PostThreadMessage失败导致的内存泄漏**【控】**1.1.4. SendMessage 时关闭客户端【控】1.1.5. 线程机制导致【**控】**1.1.6. exit&#xff08;0&#xff09;导致【…

26考研——中央处理器_指令流水线_指令流水线的基本概念 流水线的基本实现(5)

408答疑 文章目录 六、指令流水线指令流水线的基本概念流水线的基本实现流水线设计的原则流水线的逻辑结构流水线的时空图表示 八、参考资料鲍鱼科技课件26王道考研书 六、指令流水线 前面介绍的指令都是在单周期处理机中采用串行方法执行的&#xff0c;同一时刻 CPU 中只有一…

AI Agent-基础认知与架构解析

定义 AI Agent 可以理解为一种具备感知、决策和行动能力的智能实体&#xff0c;能够在复杂的环境中自主运行&#xff0c;并根据环境变化动态调整自身行为&#xff0c;以实现特定目标。与传统的人工智能程序相比&#xff0c;AI Agent 具有更强的自主性、交互性和适应性。它不仅能…