前端性能优化笔记

1.性能指标

目前行业内主流的性能指标主要基于 Web Vitals 标准,分为核心指标和辅助指标:

|------------------|-------------------------------------------------------------|----------------------------------------------------------------------------------------|
| LCP | Largest Contentful Paint最大内容绘制 | 最重要的衡量页面的加载性能指标。指视口中最大的内容元素渲染完成的时间。优秀标准:≤ 2.5秒。 |
| FID/ INP | 首次输入延迟 First Input Delay/ Interaction to Next Paint | 衡量页面的交互性。指用户首次与页面交互(如点击按钮)到浏览器实际响应的时间 FID 优秀标准:≤ 100ms;INP 优秀标准:≤ 200ms INP 正在逐步替代 FID |
| CLS | Cumulative Layout Shift,累积布局偏移 | 衡量页面的视觉稳定性。指页面加载过程中元素意外移动的程度。优秀标准:≤ 0.1。 |
| FCP | First Contentful Paint 首次内容绘制 | 浏览器首次渲染出文本、图像或 SVG 等实际内容的时间。优秀标准:≤ 1.8秒。 |
| TTFB | Time To First Byte 首字节时间): | 请求发起到收到服务器第一个字节的时间,代表服务端响应和网络速度。优秀标准:< 600ms。 |
| TBT | Total Blocking Time 总阻塞时间 | 主线程被长任务(>50ms)阻塞的总时间。优秀标准:< 200ms。 |

获取这些性能指标

获取指标通常分为"合成监控(实验室数据)"和"真实用户监控(RUM)"两种方式:

浏览器原生 PerformanceObserver 可以监听并获取 FCP、LCP、CLS 等指标

Lighthouse:Chrome DevTools 内置的自动化审计工具,可以生成包含性能、可访问性等维度的详细报告,提供具体的优化建议。

PageSpeed Insights (PSI):Google 提供的免费服务,不仅提供 Lighthouse 的实验室模拟数据,还能结合 Chrome 用户体验报告(CrUX)提供真实用户的实测数据。

WebPageTest:用于在不同地理位置、不同设备和网络环境下进行多地点性能测试。

RUM(Real User Monitoring):通过嵌入 JS 脚本收集真实用户环境下的性能数据,反映真实的设备、网络条件和地理位置表现。

2.性能优化:

  1. 网络层面优化(更快、更小)
  • 资源压缩:启用 Gzip 或 Brotli 压缩,通常能将资源体积减少 70% 以上。

  • CDN 加速:将静态资源部署到 CDN,缩短用户请求的物理距离。

  • 缓存策略:合理配置强缓存(Cache-Control)和协商缓存(Etag/Last-Modified),减少重复请求。

  • 减少请求:通过接口合并、雪碧图、小图片 Base64 内嵌等方式减少 HTTP 请求数。

  1. 资源加载优化(减少阻塞)
  • 懒加载(Lazy Loading) :对非首屏的图片和组件使用 loading="lazy" 或动态 import() 按需加载。

  • 资源预加载 :使用 <link rel="preload"> 提前加载关键资源(如字体、首屏大图);使用 preconnect 提前建立第三方连接。

  • 调整加载顺序 :CSS 放在 <head> 中避免阻塞渲染,非关键 JS 使用 deferasync 异步加载。

  1. 构建打包优化(包体积更小)
  • Tree-Shaking:利用 ES6 模块语法,剔除未使用的死代码。

  • 代码分割(Code Splitting):利用 Webpack/Vite 将代码拆分为多个 chunk,实现路由级或组件级按需加载。

  • 按需引入:第三方 UI 库(如 Element/Antd)配置按需加载,避免全量打包。

  1. 代码逻辑与渲染优化(执行更快)
  • 减少重排重绘 :避免频繁读取 offsetHeight 等触发同步布局的属性;动画尽量使用 transformopacity 开启 GPU 加速。

  • 长任务优化 :将复杂计算交给 Web Worker,或使用 requestIdleCallback 在浏览器空闲时执行非紧急任务。

  • 长列表优化:使用虚拟滚动(Virtual List),仅渲染视口内可见的 DOM 节点。

  • 内存管理:及时清理定时器、解绑事件监听,避免内存泄漏。

  1. 体验与感知优化(用户觉得更快)
  • 骨架屏(Skeleton):在内容加载完成前展示占位 UI,降低用户的白屏焦虑。

  • 交互反馈:高频操作(如搜索、滚动)使用防抖和节流;按钮点击后立即给予视觉反馈。

3.面试题

Q1:前端性能优化一般从哪些维度入手?

:通常可以从六个维度入手:网络层面(CDN、压缩、缓存)、资源加载(懒加载、预加载)、构建打包(Tree-Shaking、代码分割)、代码逻辑(减少重排、Web Worker)、浏览器渲染(关键渲染路径、GPU加速)以及体验感知(骨架屏、防抖节流)。同时,优化必须遵循"指标量化 → 工具分析 → 方案实施 → 持续监控"的闭环逻辑。

Q2:什么是 Core Web Vitals(核心网页指标)?LCP、FID、CLS 分别代表什么?

:Core Web Vitals 是 Google 定义的一组衡量用户体验的关键指标。LCP(最大内容绘制)衡量加载性能,优秀标准为 ≤2.5s;FID(首次输入延迟)衡量交互响应速度,优秀标准为 ≤100ms(现已逐步被 INP 替代);CLS(累积布局偏移)衡量视觉稳定性,优秀标准为 ≤0.1。

Q3:如何定位和解决前端性能瓶颈?

:首先通过 Lighthouse 或 Chrome DevTools 的 Performance 面板生成报告,查看 FP/FCP/LCP 等核心指标和网络瀑布图,定位是大包加载慢还是主线程长任务阻塞。然后针对性解决:如果是加载慢,采用代码分割、图片压缩、CDN 等;如果是运行卡顿,采用虚拟列表、长任务时间切片、Web Worker 等方案。最后通过 RUM 监控持续观察优化效果。

Q4:什么是代码分割(Code Splitting)?Webpack 中如何配置?

:代码分割是将代码拆分成多个按需加载的 chunk,以减小首屏 JS 体积。在 Webpack 中,可以通过 SplitChunksPlugin 提取公共依赖;对于路由或组件,可以使用动态 import() 语法实现懒加载。在 Vite 中,原生支持动态导入,也可通过 build.rollupOptions.output.manualChunks 进行分包配置。

Q5:什么是 Tree-Shaking?写代码时有哪些注意事项能让它效果更好?

:Tree-Shaking 是一种剔除未使用代码(死代码)的优化技术。要让它生效,必须使用 ES2015 的 import/export 模块语法;在编写工具库时,尽量使用命名导出(Named Export)而非默认导出(Default Export);同时,确保代码没有副作用,或者在 package.json 中正确配置了 "sideEffects" 字段。

Q6:如何设计一个前端性能监控平台?

:一个完整的监控平台包含四个核心模块:数据采集(利用 Performance API 采集 LCP、CLS 等指标,捕获 JS 错误和资源加载失败)、数据上报(使用 navigator.sendBeaconfetch 异步上报,注意采样率控制)、数据可视化(按页面、地域、设备维度展示趋势图和大盘数据)、告警机制(当核心指标劣化或错误率突增时,通过钉钉/邮件触发告警)。

4.浏览器缓存

浏览器缓存主要分为两大类,优先级:先强缓存,后协商缓存

强缓存Strong Cache:

命中后完全不向服务器发送网络请求,直接从本地读取缓存资源。

控制字段:Cache-Control

max-age=秒数(设置缓存有效期)

no-cache(跳过强缓存,走协商缓存)

no-store(完全不缓存)

public/private(控制代理服务器是否可缓存)

协商缓存Negotiated Cache

当强缓存失效或未命中时触发。浏览器会向服务器发送请求,携带缓存标识,由服务器判断资源是否更新。若未更新返回 304,浏览器使用本地缓存;若已更新则返回 200 及新资源。

控制字段:ETag / If-None-Match(优先级高):基于文件内容生成的哈希值。能精准识别文件内容是否变化

Last-Modified / If-Modified-Since:基于资源的最后修改时间。缺点是精度只到秒,且文件内容未变但被重新保存时也会失效

浏览器缓存的工作流程?

浏览器请求资源时,首先检查强缓存(Cache-Control / Expires)。如果命中且未过期,直接使用本地缓存,不发起网络请求(状态码 200 from cache);如果未命中或已过期,则进入协商缓存阶段,携带 If-None-MatchIf-Modified-Since 请求头向服务器验证。服务器比对后,若资源未变返回 304,浏览器使用本地缓存;若已变则返回 200 和新资源。

为什么 ETag 比 Last-Modified 更可靠?

Last-Modified 只能精确到秒,如果文件在 1 秒内被多次修改,它无法识别;而 ETag 基于内容哈希,能精准识别。

如果文件内容没有改变,但被重新保存或重命名,修改时间会变化导致 Last-Modified 失效,而 ETag 不会。

某些服务器可能无法准确获取文件的最后修改时间。

项目中如何设计缓存策略?

根据资源类型分类处理:

  1. 静态资源(JS/CSS/图片/字体) :采用强缓存 + 文件名哈希(指纹) 。例如配置 Cache-Control: max-age=31536000(缓存 1 年),并将文件命名为 app.[hash].js。这样只要内容不变,就一直走强缓存;内容一旦改变,哈希值变化,浏览器会将其视为新文件重新请求。
  2. HTML 入口文件协商缓存。因为 HTML 是资源的入口,更新频繁,必须每次都向服务器验证,以保证用户能加载到最新的静态资源指纹。
  3. 动态接口数据:稳定数据如字典表可使用协商缓存,频繁变动数据禁用缓存

强制刷新 (Ctrl+F5)会发生什么?

强制刷新会跳过所有的强缓存和协商缓存,浏览器会直接向服务器请求最新资源。此时请求头会自动携带 Cache-Control: no-cachePragma: no-cache,强制服务器返回 200 和最新内容。

内存缓存(Memory Cache)和磁盘缓存(Disk Cache)有什么区别?

内存缓存读取极快,但容量小,页面关闭后即失效,通常用于存放小体积或频繁访问的资源;磁盘缓存容量大、持久化,读取速度稍慢,遵循 HTTP 缓存头的规则,是大部分静态资源的归宿。

SPA缓存的幽灵旧版本问题:发版了,用户停留在旧页面没刷新,点击跳转时白屏:

原因:用户停留在旧版 HTML 页面,点击路由跳转时,前端去请求旧版本的 JS 文件(如 app.v1.js)。但服务器发版时,旧文件已经被删除,Nginx 回退返回了index.html。浏览器把 HTML 当作 JS 解析,就会报错,导致白屏

解决:

前端版本检测:在 Nginx 配置一个不缓存的 /version.json 文件,每次发版更新里面的版本号。前端通过路由切换时请求该文件,发现版本不一致时,提示用户"有新版本,请刷新"。
在全局拦截这类错误,并利用 sessionStorage 确保只自动刷新一次 (防止在网络异常时陷入死循环)

Vite内置了预加载错误的事件监听,可以直接使用官方推荐的方式:

javascript 复制代码
window.addEventListener('vite:preloadError', (event) => {
  // 发生预加载错误时,直接刷新页面获取最新的 index.html
  window.location.reload();
});

SPA 中台项目的缓存配置(以 Nginx 为例)

打包后,入口文件是 index.html,所有的业务代码都被打包成了带有哈希值的静态文件(如 app.a1b2c3d.js

javascript 复制代码
server {
    listen 80;
    server_name example.com;
    root /var/www/spa;
    index index.html;
    # 1. 入口文件:禁用强缓存,强制每次向服务器验证
    location = /index.html {
        add_header Cache-Control "no-cache, must-revalidate";
    }
    # 2. 静态资源:开启长缓存(例如7天或30天),并标记为 immutable
    location ^~ /assets/ {
        add_header Cache-Control "public, max-age=604800, immutable";
    }
    # 3. 前端路由兜底(SPA 必备)
    location / {
        try_files $uri $uri/ /index.html;
    }
}

5.懒加载

懒加载又称为延迟加载或按需加载,是一种优化网页或应用加载时间的技术策略。它的核心思想是:将非关键资源(如图片、视频、代码块等)的加载延迟到真正需要它们的时候。在长网页中,只有当用户滚动到该资源所在的可视区域时,才会触发实际的加载请求。

首屏加速:显著减少首屏的 HTTP 请求数,缩短关键渲染路径,让用户更快看到页面核心内容。

节省资源:避免加载用户可能永远不会查看的内容,节省带宽、服务器资源及浏览器内存。

提升用户体验:减少并发加载过多资源导致的 JS 阻塞,让页面交互更流畅,降低跳出率。

懒加载原理

占位与隐藏真实地址

浏览器只有在解析到 <img> 标签的 src 属性时才会发起请求。因此,懒加载会将真实的资源 URL 存放在自定义属性(如 data-src)中,而将 src 指向一个极小的占位图(如 loading.gif)或留空。

监听与替换

通过监听用户的滚动行为,判断资源元素是否进入了浏览器的可视区域。一旦进入,就通过 JavaScript 将 data-src 的值赋给 src,从而触发真实的资源加载。

实现方式

随着浏览器 API 的演进,懒加载的实现方式经历了以下迭代:

  1. 原生 HTML 属性(现代推荐):现代浏览器原生支持 loading="lazy" 属性。只需给 <img><iframe> 添加该属性,浏览器会自动接管延迟加载逻辑,这是目前最简洁、性能最好的方案。

  2. Intersection Observer API(现代 JS 推荐):这是目前最主流的手写懒加载方案。它不依赖高频的滚动事件,而是利用浏览器底层的异步观察者机制,高效检测元素与视口的交叉状态,性能极佳。

  3. 滚动事件监听(传统方案):通过监听 window.onscroll 事件,结合 getBoundingClientRect()offsetTop 计算元素位置。由于滚动事件触发极其频繁,通常需要配合防抖(Debounce)或节流(Throttle)使用,否则容易导致页面卡顿。

路由懒加载(router/index.js)

import Home from '../views/Home.vue'在路由表中直接引用是未使用懒加载

使用懒加载时,路由组件通过动态的 import() 函数引入

component: () => import('../views/Home.vue')

在 React 中使用了 React.lazy() 包裹来实现懒加载

Vue 项目懒加载策略

  • 路由懒加载:使用 () => import() 将非首屏页面拆分

  • 组件懒加载:针对弹窗、抽屉、富文本编辑器、数据图表等非首屏、重型、触发式使用的组件,使用 Vue3 的 defineAsyncComponent 进行按需加载

  • 逻辑与模块的懒执行:避免在 setup 顶层同步导入大模块(如 Excel 处理库、PDF 生成器)。应改在用户点击触发后,通过 await import() 动态加载并缓存,避免首屏加载无用逻辑。

React 项目懒加载策略:Suspense 与 Error Boundary 结合

  • 路由懒加载:使用 React.lazy 配合 Suspense 实现路由级按需加载,显著减少初始包体积。

  • 组件懒加载:针对条件渲染的组件(如仅管理员可见的后台面板)或大型图表,使用 React.lazy 包裹,并在特定交互时再渲染。

  • 异常容错处理:懒加载组件可能因网络问题加载失败,必须使用 Error Boundary(错误边界) 捕获异常,提供友好的降级 UI 或重试按钮,防止整页白屏崩溃。

前端优化点(工程化与网络层)

  1. Chunk 分组与命名优化(避免请求风暴)

过度细分代码会导致 HTTP 请求数量激增。在实际项目中,应通过 Webpack 的魔法注释(如 webpackChunkName)或 Vite 的 manualChunks 配置,将语义相关或同属一个业务模块的组件合并打包(例如将多个报表组件合并为 charts.js),在减少包体积和控制请求数量之间找到平衡。

  1. 预加载与预取策略(Prefetch & Preload)
  • Preload:对当前页面核心关键资源提前拉取,避免阻塞渲染。

  • Prefetch:利用浏览器空闲时间,提前获取用户极可能访问的路由组件资源(如鼠标悬停在导航链接时触发低优先级 fetch)。这能实现路由切换时的"无感秒开",大幅提升用户感知性能。

  1. 结合 Intersection Observer 实现视口级懒加载

对于长列表中的折叠区域或滚动触达模块,仅靠路由懒加载是不够的。进阶做法是结合 Intersection Observer API 监听 DOM 元素是否进入视口,当元素即将可见时才触发 defineAsyncComponentimport() 加载,实现真正的"按需渲染"。

  1. 缓存与状态分层策略
  • 组件缓存:在 Vue 中,对高频核心组件(如 Header、Dashboard)使用 <keep-alive> 进行永久缓存,对低频工具组件限制最大缓存数量(如 max=5),避免内存无限增长。

  • 第三方依赖拆分:将 React/Vue 核心库、UI 组件库、Axios 等稳定依赖单独拆包(Vendor Chunk),利用浏览器的长效缓存机制,避免每次发版都重复下载。

实战避坑

  1. 首屏内容绝不懒加载:核心首页、高频页面的关键资源应同步加载,保证基础体验,避免首屏白屏或布局抖动。

  2. 解决 Loading 闪烁问题:在网络极快时,懒加载组件可能瞬间加载完成,导致 fallback(Loading 状态)一闪而过。可以通过自定义 Hook 设置最小显示时间(如 300ms),或使用 CSS 过渡动画平滑显示占位内容。

  3. SSR 环境下的兼容:在服务端渲染(SSR)项目中,懒加载组件在服务端默认不执行。需配合 ssr: falseno-ssr 标签避免水合(Hydration)异常,或者使用 Loadable Components 等第三方库实现同构加载。

图片懒加载的实现原理?

先将图片的真实地址存放在 data-src 属性中,src 属性设为占位图。然后通过 IntersectionObserver API 监听这些图片元素。当图片进入浏览器可视区域时,触发回调函数,将 data-src 的值赋给 src,完成图片的真实加载。加载完成后,停止对该元素的观察。

懒加载和预加载(Preload)有什么区别?

两者的目的都是提升用户体验,但策略完全相反。

  • 懒加载(Lazy Load):是"按需分配",延迟加载非可视区域的资源,能减少初始请求,缓解服务器压力。

  • 预加载(Preload):是"提前准备",在资源使用前就提前请求并放入缓存。当真正使用时直接从缓存读取,适用于九宫格抽奖等对切换速度要求极高的场景,但会增加初始的网络和服务器压力。

懒加载对 SEO 有影响吗?

传统的滚动监听懒加载可能会导致搜索引擎爬虫无法触发滚动,从而无法抓取和索引懒加载的内容,对 SEO 产生负面影响。

解决方案:使用原生的 loading="lazy" 属性或 IntersectionObserver API,现代搜索引擎爬虫已经能够较好地识别这些标准实现。此外,务必为图片添加准确的 alt 文本和语义化标签,确保爬虫能获取到关键信息。

除了图片,懒加载还有哪些应用场景?

  1. 路由级懒加载:在 SPA(单页应用)中,通过动态 import() 语法按需加载路由组件,极大减小首屏 JS 包体积。

  2. 长列表/大数据渲染:结合虚拟列表(Virtual List)技术,只渲染可视区域内的 DOM 节点,解决万级数据渲染导致的浏览器卡顿问题。

  3. 第三方组件/重型库懒加载:如富文本编辑器、图表库等,在用户触发特定交互时才去加载相关代码。

手写懒加载如何保证良好的用户体验?

在资源加载完成前,应使用轻量级的占位符(如低分辨率预览图 LQIP、骨架屏 Skeleton Screen 或纯色背景)来防止页面布局突然变化(CLS)。同时,需要处理加载失败的情况,提供重试机制或错误兜底图,确保用户体验不受损。

6.预加载Preload&预取Prefetch

预取(Prefetch)和预加载(Preload)是前端性能优化中非常重要,但也极易混淆的两个概念。它们的核心目的都是"提前获取资源,减少用户等待时间",但优先级、触发时机和应用场景完全不同。

对比维度 预加载(Preload) 预取(Prefetch)
目标资源 当前页面必需的关键资源 未来导航可能用到的资源
优先级 极高(抢占带宽) 极低(空闲时执行)
资源类型 字体、首屏大图、核心JS/CSS 下一个路由的 JS Chunk、下一页 HTML
核心目的 消除当前页面的加载阻塞 实现未来页面的"秒开"

预加载(Preload)

Preload 之所以能带来显著的性能提升,核心原因不在于它能让网络下载变得"更快",而在于它打破了浏览器默认的"资源发现与加载的串行依赖",把原本串行的工作变成了并行工作。

不使用 Preload:串行阻塞(瀑布流效应)

首屏需要一张关键大图(LCP 元素),而这张图片是在 CSS 文件中通过 background-image 引用的。

  1. HTML 解析:浏览器下载并解析 HTML,发现需要请求 CSS 文件。

  2. CSS 下载:浏览器发起网络请求下载 CSS 文件。

  3. CSS 解析:CSS 下载完成,浏览器开始解析 CSS 规则。

  4. 图片发现:解析到 background-image 时,浏览器此时才发现需要这张图片。

  5. 图片下载:浏览器才发起网络请求去下载这张图片。

图片的下载被严重延后了。它必须等待 HTML 下载完、CSS 下载完、CSS 解析完才能开始。这就形成了严重的"请求瀑布流(Waterfall)",导致首屏渲染时间(LCP)被大幅拉长。

使用 Preload:并行下载(消除瀑布流)

如果你在 <head> 中加了 <link rel="preload" href="hero.jpg" as="image">,流程会变成这样:

  1. HTML 解析:浏览器下载并解析 HTML,在 <head> 中第一时间发现了 Preload 指令。

  2. 并行下载:浏览器立刻以高优先级发起对 hero.jpg 的网络请求。同时,它也在后台下载 CSS 文件。

  3. CSS 解析:CSS 下载并解析完成,渲染引擎准备绘制首屏。

  4. 命中缓存:渲染引擎发现需要 hero.jpg,去缓存中一找,发现 Preload 早就把它下载好放在内存里了!直接读取,无需再次发起网络请求。

图片的下载与 CSS 的下载是同时(并行)进行的。图片的下载时间被"提前"了,省去了等待 CSS 下载和解析的漫长耗时。

Preload 并没有缩短网络传输的物理时间,但它提前了下载开始的起跑线,让关键资源能和主文档一起"赛跑",从而实现了首屏的极速渲染。

① 在 HTML 中声明(最推荐用于字体和首屏大图)

<head> 标签中使用 <link rel="preload">,必须指定 as 属性告诉浏览器资源类型

javascript 复制代码
<!-- 预加载自定义字体,消除文字闪烁(FOIT/FOUT) -->
<link rel="preload" href="custom-font.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<!-- 预加载首屏核心大图 -->
<link rel="preload" href="hero-image.jpg" as="image">

② 在 JavaScript 中动态预加载(用于动态路由或按需加载的组件)

javascript 复制代码
// 当用户进入某个页面时,提前预加载一个稍后才会用到的重型组件
const preloadHeavyComponent = () => {
  const link = document.createElement('link');
  link.rel = 'preload';
  link.href = '/assets/heavy-chart.js';
  link.as = 'script';
  document.head.appendChild(link);
};

预取(Prefetch)的实战做法

① 结合构建工具(Webpack/Vite)实现路由预取

这是 SPA 项目中最常用的手段。当用户停留在首页时,利用网络空闲提前下载其他页面的代码

javascript 复制代码
// Webpack 魔法注释:浏览器空闲时预取用户中心页面的代码
const UserView = () => import(/* webpackPrefetch: true */ '../views/UserView.vue');

// Vite 项目同样支持动态 import 配合特定的插件实现预取

② 在 HTML 中声明(用于传统多页应用或明确的外部链接)

javascript 复制代码
<!-- 预取下一页的内容 -->
<link rel="prefetch" href="/api/next-page-data">

③ 现代浏览器的新标准:推测规则 API(Speculation Rules API)

这是目前最前沿的预取方案,允许你以声明式的方式告诉浏览器预取或预渲染哪些链接

javascript 复制代码
<script type="speculationrules">
{
  "prefetch": [{
    "source": "list",
    "urls": ["/next-page.html", "/search-results.html"]
  }]
}
</script>

避坑指南

  1. 切忌滥用 Preload:Preload 是高优先级的,如果预加载了当前页面根本不需要的资源,反而会阻塞真正关键资源的下载,导致首屏变慢。

  2. 注意移动端弱网环境:在移动端或弱网环境下,过度使用 Prefetch 会消耗用户的流量和电量。现代浏览器在用户开启"省电模式"或"流量节省模式"时,会自动忽略 Prefetch 请求。

  3. Preload 的 CORS 问题:如果预加载的是跨域资源(尤其是字体),必须加上 crossorigin="anonymous" 属性,否则浏览器会下载两次(一次预加载,一次实际使用)。

  4. 缓存策略的配合:预取回来的资源,依然要遵循我们之前聊过的 HTTP 缓存策略。如果预取的资源没有设置合理的 Cache-Control,依然无法发挥"秒开"的威力。

一句话总结:Preload 用来保当前页面的首屏极速渲染,Prefetch 用来保未来页面的无缝切换。

相关推荐
带娃的IT创业者1 小时前
单文件架构的极致美学:深入解析 Bento 的 HTML 幻灯片技术实现
前端·架构·html·web开发·bento·单文件架构
muddjsv1 小时前
CSS 值的完整计算过程:指定值、计算值、使用值、实际值与动态依赖
前端·css
恋猫de小郭1 小时前
KotlinLLM 开源 ,一个可以在运行时自己生成永久 Kotlin 代码的 Agent 库
android·前端·人工智能
名字还没想好☜1 小时前
React createPortal 实战:模态框逃出 overflow:hidden、事件冒泡与焦点管理
前端·javascript·react.js·ecmascript·react·createportal
用户059540174461 小时前
Playwright测试AI记忆存储踩坑实录:这个时序问题让我排查了6小时
前端·css
IT_陈寒1 小时前
Redis踩了个大坑,原来DEL命令也会卡住整个实例
前端·人工智能·后端
是上好佳佳佳呀2 小时前
【机器学习|DAY06】集成学习(Ensemble Learning)笔记
笔记·机器学习·集成学习
kdxiaojie2 小时前
Linux 驱动研究 —— V4L2 (14)
linux·运维·笔记·学习
一个水瓶座程序猿.2 小时前
基于Spring AI RAG 的AI知识库前端交互实现
前端·人工智能·spring