<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>性能优化 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/performance/</link><description>Recent content in 性能优化 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 17 Jul 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/posts/frontend/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>浏览器渲染过程</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-001/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-001/</guid><description>&lt;h2 id="渲染流程"&gt;渲染流程&lt;/h2&gt;
&lt;p&gt;首先要了解的概念:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;渲染引擎：它是浏览器最核心的部分是 “Rendering Engine”，不过我们一般习惯将之称为 “浏览器内核”&lt;/li&gt;
&lt;li&gt;渲染引擎主要包括的线程：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-001/image-01.webp"&gt;&lt;/p&gt;
&lt;p&gt;各个线程主要职责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GUI渲染线程&lt;/strong&gt;：GUI 渲染线程负责渲染浏览器界面，解析 HTML，CSS，构建 DOM 树和 RenderObject 树，布局和绘制等。当界面需要重绘（Repaint）或由于某种操作引发回流（Reflow）时，该线程就会执行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript引擎线程&lt;/strong&gt;: JavaScript 引擎线程主要负责解析 JavaScript 脚本并运行相关代码。 JavaScript 引擎在一个Tab页（Renderer 进程）中无论什么时候都只有一个 JavaScript 线程在运行 JavaScript 程序。需要提起一点就是，GUI线程与JavaScript引擎线程是互斥的，这也是就是为什么JavaScript操作时间过长，会造成页面渲染不连贯，导致页面出现阻塞的原理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;事件触发线程&lt;/strong&gt;：当一个事件被触发时该线程会把事件添加到待处理队列的队尾，等待 JavaScript 引擎的处理。 通常JavaScript引擎是单线程的，所以这些事件都会排队等待JS执行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;定时器触发器&lt;/strong&gt;： 我们日常使用的setInterval 和 setTimeout 就在该线程中，原因可能就是：由于JS引擎是单线程的，如果处于阻塞线程状态就会影响记时的准确，所以需要通过单独的线程来记时并触发响应的事件这样子更为合理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Http请求线程&lt;/strong&gt;： 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求，这个线程就Http请求线程，它 将检测到状态变更时，如果设置有回调函数，异步线程就产生状态变更事件放到 JavaScript 引擎的处理队列中等待处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;有了上述的概念，对接下我们讲渲染流水线会有所帮助&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="简略版的渲染机制"&gt;简略版的渲染机制&lt;/h2&gt;
&lt;p&gt;很久之前就把浏览器工作原理读完了，看了很多博客，文章，当时简简单单的梳理一些内容,如下👇&lt;/p&gt;
&lt;p&gt;简略版渲染机制一般分为以下几个步骤&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;处理 HTML 并构建 DOM 树。&lt;/li&gt;
&lt;li&gt;处理 CSS 构建 CSSOM 树。&lt;/li&gt;
&lt;li&gt;将 DOM 与 CSSOM 合并成一个渲染树。&lt;/li&gt;
&lt;li&gt;根据渲染树来布局，计算每个节点的位置。&lt;/li&gt;
&lt;li&gt;调用 GPU 绘制，合成图层，显示在屏幕上。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-001/image-02.webp"&gt;&lt;/p&gt;
&lt;p&gt;接下来大概就是这么说：&lt;/p&gt;
&lt;p&gt;在构建 CSSOM 树时，会阻塞渲染，直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程，所以应该尽量保证层级扁平，减少过度层叠，越是具体的 CSS 选择器，执行速度越慢。&lt;/p&gt;</description></item><item><title>浏览器的缓存机制</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-002/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-002/</guid><description>&lt;h2 id="一前言"&gt;一、前言&lt;/h2&gt;
&lt;p&gt;缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离，减少延迟，并且由于缓存文件可以重复利用，还可以减少带宽，降低网络负荷。&lt;/p&gt;
&lt;p&gt;对于一个数据请求来说，可以分为发起网络请求、后端处理、浏览器响应三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发起请求，或者发起了请求但后端存储的数据和前端一致，那么就没有必要再将数据回传回来，这样就减少了响应数据。&lt;/p&gt;
&lt;p&gt;接下来的内容中我们将通过缓存位置、缓存策略以及实际场景应用缓存策略来探讨浏览器缓存机制。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如需获取思维导图或想阅读更多优质文章请猛戳&lt;a href="https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fljianshu%2FBlog"&gt;GitHub博客&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-002/image-01.webp"&gt;&lt;/p&gt;
&lt;h2 id="二缓存位置"&gt;二、缓存位置&lt;/h2&gt;
&lt;p&gt;从缓存位置上来说分为四种，并且各自有优先级，当依次查找缓存且都没有命中的时候，才会去请求网络。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Service Worker&lt;/li&gt;
&lt;li&gt;Memory Cache&lt;/li&gt;
&lt;li&gt;Disk Cache&lt;/li&gt;
&lt;li&gt;Push Cache&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="1service-worker"&gt;1.Service Worker&lt;/h3&gt;
&lt;p&gt;Service Worker 是运行在浏览器背后的独立线程，一般可以用来实现缓存功能。使用 Service Worker的话，传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截，所以必须使用 HTTPS 协议来保障安全。&lt;strong&gt;Service Worker 的缓存与浏览器其他内建的缓存机制不同，它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存，并且缓存是持续性的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Service Worker 实现缓存功能一般分为三个步骤：首先需要先注册 Service Worker，然后监听到 install 事件以后就可以缓存需要的文件，那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存，存在缓存的话就可以直接读取缓存文件，否则就去请求数据。&lt;/p&gt;
&lt;p&gt;当 Service Worker 没有命中缓存的时候，我们需要去调用 fetch 函数获取数据。也就是说，如果我们没有在 Service Worker 命中缓存的话，会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据，浏览器都会显示我们是从 Service Worker 中获取的内容。&lt;/p&gt;
&lt;h3 id="2memory-cache"&gt;2.Memory Cache&lt;/h3&gt;
&lt;p&gt;Memory Cache 也就是内存中的缓存，主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效，可是缓存持续性很短，会随着进程的释放而释放。 &lt;strong&gt;一旦我们关闭 Tab 页面，内存中的缓存也就被释放了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;那么既然内存缓存这么高效，我们是不是能让数据都存放在内存中呢？&lt;/strong&gt; 这是不可能的。计算机中的内存一定比硬盘容量小得多，操作系统需要精打细算内存的使用，所以能让我们使用的内存必然不多。&lt;/p&gt;
&lt;p&gt;当我们访问过页面以后，再次刷新页面，可以发现很多数据都来自于内存缓存&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-002/image-02.webp"&gt;&lt;/p&gt;
&lt;p&gt;内存缓存中有一块重要的缓存资源是preloader相关指令（例如&lt;code&gt;&amp;lt;link rel=&amp;quot;prefetch&amp;quot;&amp;gt;&lt;/code&gt;）下载的资源。总所周知preloader的相关指令已经是页面优化的常见手段之一，它可以一边解析js/css文件，一边网络请求下一个资源。&lt;/p&gt;
&lt;p&gt;需要注意的事情是，&lt;strong&gt;内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值，同时资源的匹配也并非仅仅是对URL做匹配，还可能会对Content-Type，CORS等其他特征做校验&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="3disk-cache"&gt;3.Disk Cache&lt;/h3&gt;
&lt;p&gt;Disk Cache 也就是存储在硬盘中的缓存，读取速度慢点，但是什么都能存储到磁盘中，&lt;strong&gt;比之 Memory Cache 胜在容量和存储时效性上&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>浏览器的垃圾回收机制</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-003/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-003/</guid><description>&lt;p&gt;浏览器的垃圾回收（Garbage Collection, GC）机制是前端性能优化和内存管理的重要基础。&lt;/p&gt;
&lt;h2 id="一垃圾回收的基本概念"&gt;一、垃圾回收的基本概念&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目的&lt;/strong&gt;：自动回收不再使用的内存，避免内存泄漏，保证浏览器性能稳定。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GC 触发&lt;/strong&gt;：当浏览器检测到内存不足或特定条件时，启动垃圾回收过程。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二主要垃圾回收算法"&gt;二、主要垃圾回收算法&lt;/h2&gt;
&lt;h3 id="1-标记清除mark-and-sweep"&gt;1. 标记清除（Mark-and-Sweep）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;浏览器从**根对象（Global、执行上下文中的变量）**开始，标记所有可达对象。&lt;/li&gt;
&lt;li&gt;没被标记的对象被认为不可达，即不再被使用，进行回收。&lt;/li&gt;
&lt;li&gt;是现代 JS 引擎普遍采用的算法。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-引用计数reference-counting"&gt;2. 引用计数（Reference Counting）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每个对象维护引用计数，引用增加时计数+1，引用消失时计数-1。&lt;/li&gt;
&lt;li&gt;计数为 0 的对象立即回收。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺陷：无法处理循环引用&lt;/strong&gt;，现代引擎一般不单独使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="三垃圾回收的触发时机"&gt;三、垃圾回收的触发时机&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;内存分配达到一定阈值时自动触发。&lt;/li&gt;
&lt;li&gt;主动调用相关接口（如 Chrome DevTools 手动触发）。&lt;/li&gt;
&lt;li&gt;页面卸载时进行清理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="四内存泄漏常见原因"&gt;四、内存泄漏常见原因&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;全局变量未释放&lt;/strong&gt; 全局变量一直被引用，无法回收。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;闭包导致的变量无法释放&lt;/strong&gt; 闭包作用域内变量被外部引用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;定时器未清除&lt;/strong&gt; &lt;code&gt;setInterval&lt;/code&gt;、&lt;code&gt;setTimeout&lt;/code&gt; 未正确清除，导致引用保留。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DOM 节点引用未释放&lt;/strong&gt; JS 中持有对已删除 DOM 的引用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;事件监听未移除&lt;/strong&gt; 绑定事件后，未及时解绑，导致内存无法回收。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="五性能优化建议"&gt;五、性能优化建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;避免不必要的全局变量。&lt;/li&gt;
&lt;li&gt;使用完定时器及时清除。&lt;/li&gt;
&lt;li&gt;解绑不再使用的事件监听。&lt;/li&gt;
&lt;li&gt;谨慎使用闭包，避免无用变量持久存在。&lt;/li&gt;
&lt;li&gt;小心操作 DOM，及时释放引用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="常见考点"&gt;常见考点&lt;/h2&gt;
&lt;p&gt;面试中考察点主要包括 GC 的原理、算法、触发时机、内存泄漏原因及避免方法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;浏览器垃圾回收的原理和常见算法？&lt;/li&gt;
&lt;li&gt;标记清除与引用计数的区别与优缺点？&lt;/li&gt;
&lt;li&gt;什么是内存泄漏？常见的内存泄漏类型？&lt;/li&gt;
&lt;li&gt;如何避免内存泄漏？&lt;/li&gt;
&lt;li&gt;JS 引擎如何判断对象是否可回收？&lt;/li&gt;
&lt;li&gt;浏览器中 GC 触发的时机？&lt;/li&gt;
&lt;li&gt;如何用 Chrome DevTools 监测内存泄漏？&lt;/li&gt;
&lt;li&gt;事件监听和闭包如何导致内存泄漏？&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>浏览器的存储机制</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-004/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/performance/performance-004/</guid><description>&lt;p&gt;浏览器的存储机制涵盖多种技术，目的是满足 Web 应用在不同场景下的数据持久化、缓存和离线访问需求。它们各自具有不同的存储容量、生命周期、安全策略和访问方式，理解这些机制对于构建高效、安全的前端应用至关重要。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="一浏览器存储机制分类"&gt;一、浏览器存储机制分类&lt;/h3&gt;
&lt;h4 id="1-cookie"&gt;1. Cookie&lt;/h4&gt;
&lt;p&gt;最早期的存储机制，主要用于会话管理和身份认证。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;容量限制&lt;/strong&gt;：单个约 4KB，总数有限制；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生命周期&lt;/strong&gt;：可设置过期时间或为会话级；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问方式&lt;/strong&gt;：由浏览器自动在 HTTP 请求头中携带，也能通过 JS 访问（除非设置 HttpOnly）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安全性&lt;/strong&gt;：可设置 HttpOnly、Secure、SameSite 防范安全风险。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-web-storagelocalstorage-和-sessionstorage"&gt;2. Web Storage（LocalStorage 和 SessionStorage）&lt;/h4&gt;
&lt;p&gt;HTML5 新增的简单键值对存储方案。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LocalStorage&lt;/strong&gt;：永久存储，关闭浏览器数据仍保留，同源可访问；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SessionStorage&lt;/strong&gt;：页面会话存储，关闭标签页即清空；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;容量&lt;/strong&gt;：一般为 5~10MB；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问方式&lt;/strong&gt;：同步 API，容易使用但可能阻塞主线程。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-indexeddb"&gt;3. IndexedDB&lt;/h4&gt;
&lt;p&gt;浏览器内置的底层结构化数据库，支持事务和索引，适合复杂和大容量数据存储。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;容量&lt;/strong&gt;：远大于 LocalStorage，通常以设备剩余空间为限；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问方式&lt;/strong&gt;：异步 API，支持复杂操作；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用途&lt;/strong&gt;：离线应用、大数据缓存、文件存储等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="4-cache-storage"&gt;4. Cache Storage&lt;/h4&gt;
&lt;p&gt;由 Service Worker 管理的请求和响应缓存，用于离线和加速访问。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;容量&lt;/strong&gt;：较大，依赖设备和浏览器策略；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问方式&lt;/strong&gt;：异步 Promise API；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用途&lt;/strong&gt;：缓存静态资源、接口响应，实现离线支持。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="5-service-worker"&gt;5. Service Worker&lt;/h4&gt;
&lt;p&gt;虽然不是存储机制本身，但作为浏览器后台代理进程，管理 Cache Storage，实现网络请求拦截和缓存策略，是现代离线应用的核心。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;生命周期独立于页面&lt;/strong&gt;，可在后台运行；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;控制页面的网络请求&lt;/strong&gt;，提供离线能力和资源预缓存；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可结合 Cache Storage 和 IndexedDB 进行数据管理&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="二存储机制的生命周期与访问作用域"&gt;二、存储机制的生命周期与访问作用域&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cookie&lt;/strong&gt;：基于域和路径，可设置 HttpOnly、Secure 限制访问；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LocalStorage/SessionStorage&lt;/strong&gt;：基于同源策略，SessionStorage 进一步限定于标签页会话；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IndexedDB 和 Cache Storage&lt;/strong&gt;：基于同源，支持版本控制和升级；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Worker&lt;/strong&gt;：独立于页面，能控制同源下的所有相关页面。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="三容量限制与性能影响"&gt;三、容量限制与性能影响&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cookie&lt;/strong&gt; 容量最小，且会随每次请求自动发送，影响网络性能；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LocalStorage/SessionStorage&lt;/strong&gt; 适合轻量存储，容量适中；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IndexedDB 和 Cache Storage&lt;/strong&gt; 容量大，适合海量数据和文件缓存；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Worker&lt;/strong&gt; 通过异步调度，避免阻塞主线程。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="四安全与隐私考虑"&gt;四、安全与隐私考虑&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cookie&lt;/strong&gt; 可被服务器访问，设置 HttpOnly 避免脚本窃取；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Storage、IndexedDB&lt;/strong&gt; 只能由同源脚本访问，防止跨站数据泄漏；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Worker&lt;/strong&gt; 需 HTTPS 环境，避免被恶意注入；&lt;/li&gt;
&lt;li&gt;用户隐私模式下，存储行为可能受限，数据不保证持久。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="五应用场景及选择建议"&gt;五、应用场景及选择建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;需要与服务器频繁交互、会话维持时用 Cookie；&lt;/li&gt;
&lt;li&gt;存储简单配置、少量数据用 LocalStorage；&lt;/li&gt;
&lt;li&gt;页面会话临时数据用 SessionStorage；&lt;/li&gt;
&lt;li&gt;大规模结构化数据和离线存储用 IndexedDB；&lt;/li&gt;
&lt;li&gt;静态资源及请求缓存用 Cache Storage，配合 Service Worker 提升离线体验和性能；&lt;/li&gt;
&lt;li&gt;Service Worker 负责管理缓存和拦截网络请求，实现 PWA 功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="常见考点"&gt;常见考点&lt;/h2&gt;
&lt;p&gt;面试考察点通常围绕存储类型、特点、使用场景、容量限制、安全性和生命周期展开：&lt;/p&gt;</description></item></channel></rss>