前端缓存策略:让你的应用飞起来
前端缓存策略让你的应用飞起来一、引言又到了我这个毒舌工匠上线的时间了今天咱们来聊聊前端缓存策略这个话题。别以为缓存只是后端的事情前端缓存同样重要。一个好的缓存策略能够大大提高应用的性能和用户体验让你的应用飞起来。二、什么是前端缓存前端缓存就是将数据存储在浏览器中以便下次访问时能够快速获取而不需要从服务器重新请求。简单来说就是让浏览器记住一些数据下次用的时候直接拿不用再去服务器要。三、前端缓存的类型1. HTTP缓存HTTP缓存是基于HTTP协议的缓存机制包括强缓存和协商缓存。1.1 强缓存强缓存是指浏览器直接从缓存中获取资源不需要向服务器发送请求。相关HTTP头Expires指定资源的过期时间Cache-Control控制缓存的行为包括max-age、no-cache、no-store等代码示例// 服务器设置强缓存 app.get(/static/js/app.js, (req, res) { res.setHeader(Cache-Control, max-age31536000); // 1年 res.sendFile(path.join(__dirname, static/js/app.js)); });1.2 协商缓存协商缓存是指浏览器向服务器发送请求服务器根据请求头判断资源是否有更新如果没有更新则返回304 Not Modified浏览器从缓存中获取资源。相关HTTP头Last-Modified资源的最后修改时间If-Modified-Since浏览器发送的请求头包含资源的最后修改时间ETag资源的唯一标识符If-None-Match浏览器发送的请求头包含资源的ETag代码示例// 服务器设置协商缓存 app.get(/api/data, (req, res) { const data { message: Hello World }; const etag generateETag(data); if (req.headers[if-none-match] etag) { res.status(304).end(); return; } res.setHeader(ETag, etag); res.json(data); });2. 浏览器存储浏览器存储是指在浏览器中存储数据的机制包括 localStorage、sessionStorage、IndexedDB 等。2.1 localStoragelocalStorage是一种持久化的存储机制数据会一直存储在浏览器中直到被手动删除。代码示例// 存储数据 localStorage.setItem(user, JSON.stringify({ name: 张三, age: 20 })); // 获取数据 const user JSON.parse(localStorage.getItem(user)); // 删除数据 localStorage.removeItem(user); // 清空所有数据 localStorage.clear();2.2 sessionStoragesessionStorage是一种会话级别的存储机制数据只在当前会话中有效关闭浏览器窗口后数据会被删除。代码示例// 存储数据 sessionStorage.setItem(token, abc123); // 获取数据 const token sessionStorage.getItem(token); // 删除数据 sessionStorage.removeItem(token); // 清空所有数据 sessionStorage.clear();2.3 IndexedDBIndexedDB是一种功能强大的浏览器存储机制支持存储大量数据并且支持索引和事务。代码示例// 打开数据库 const request indexedDB.open(myDB, 1); request.onupgradeneeded (event) { const db event.target.result; // 创建对象存储空间 const store db.createObjectStore(users, { keyPath: id }); // 创建索引 store.createIndex(name, name, { unique: false }); }; request.onsuccess (event) { const db event.target.result; // 开始事务 const transaction db.transaction(users, readwrite); const store transaction.objectStore(users); // 添加数据 store.add({ id: 1, name: 张三, age: 20 }); // 获取数据 store.get(1).onsuccess (event) { console.log(event.target.result); }; // 提交事务 transaction.oncomplete () { db.close(); }; };3. Service Worker 缓存Service Worker 缓存是一种基于 Service Worker 的缓存机制能够实现离线访问。代码示例// service-worker.js const CACHE_NAME my-cache-v1; const urlsToCache [ /, /index.html, /static/js/app.js, /static/css/app.css ]; // 安装 Service Worker self.addEventListener(install, (event) { event.waitUntil( caches.open(CACHE_NAME) .then((cache) { console.log(Opened cache); return cache.addAll(urlsToCache); }) ); }); // 激活 Service Worker self.addEventListener(activate, (event) { const cacheWhitelist [CACHE_NAME]; event.waitUntil( caches.keys().then((cacheNames) { return Promise.all( cacheNames.map((cacheName) { if (cacheWhitelist.indexOf(cacheName) -1) { return caches.delete(cacheName); } }) ); }) ); }); // 拦截请求 self.addEventListener(fetch, (event) { event.respondWith( caches.match(event.request) .then((response) { if (response) { return response; } return fetch(event.request); }) ); });四、前端缓存的最佳实践1. 合理设置HTTP缓存合理设置HTTP缓存是前端缓存的基础。你应该根据资源的性质设置不同的缓存策略。静态资源对于长期不变的静态资源如图片、字体等使用强缓存设置较长的过期时间。对于经常变化的静态资源如JS、CSS等使用协商缓存或者在文件名中添加版本号。代码示例// 对于长期不变的静态资源 app.get(/static/images/logo.png, (req, res) { res.setHeader(Cache-Control, max-age31536000); // 1年 res.sendFile(path.join(__dirname, static/images/logo.png)); }); // 对于经常变化的静态资源 app.get(/static/js/app.js, (req, res) { res.setHeader(Cache-Control, no-cache); // 强制协商缓存 res.sendFile(path.join(__dirname, static/js/app.js)); });2. 使用浏览器存储存储用户数据使用浏览器存储存储用户数据是前端缓存的重要组成部分。你可以使用 localStorage 存储用户的偏好设置、购物车等数据使用 sessionStorage 存储会话相关的数据。代码示例// 存储用户偏好设置 localStorage.setItem(theme, dark); localStorage.setItem(fontSize, 16px); // 存储购物车数据 localStorage.setItem(cart, JSON.stringify([ { id: 1, name: 商品1, price: 100, quantity: 1 }, { id: 2, name: 商品2, price: 200, quantity: 2 } ])); // 存储会话相关的数据 sessionStorage.setItem(token, abc123); sessionStorage.setItem(userId, 123);3. 使用Service Worker实现离线访问使用Service Worker实现离线访问是前端缓存的高级应用。你可以使用 Service Worker 缓存静态资源实现离线访问。代码示例// service-worker.js const CACHE_NAME my-cache-v1; const urlsToCache [ /, /index.html, /static/js/app.js, /static/css/app.css, /static/images/logo.png ]; // 安装 Service Worker self.addEventListener(install, (event) { event.waitUntil( caches.open(CACHE_NAME) .then((cache) { console.log(Opened cache); return cache.addAll(urlsToCache); }) ); }); // 激活 Service Worker self.addEventListener(activate, (event) { const cacheWhitelist [CACHE_NAME]; event.waitUntil( caches.keys().then((cacheNames) { return Promise.all( cacheNames.map((cacheName) { if (cacheWhitelist.indexOf(cacheName) -1) { return caches.delete(cacheName); } }) ); }) ); }); // 拦截请求 self.addEventListener(fetch, (event) { event.respondWith( caches.match(event.request) .then((response) { if (response) { return response; } return fetch(event.request) .then((response) { if (!response || response.status ! 200 || response.type ! basic) { return response; } const responseToCache response.clone(); caches.open(CACHE_NAME) .then((cache) { cache.put(event.request, responseToCache); }); return response; }); }) ); });4. 缓存策略的选择缓存策略的选择是前端缓存的关键。你应该根据资源的性质和应用的需求选择合适的缓存策略。常见的缓存策略Cache First优先从缓存中获取资源如果缓存中没有则从服务器获取。Network First优先从服务器获取资源如果网络请求失败则从缓存中获取。Stale While Revalidate从缓存中获取资源的同时从服务器获取新资源更新缓存。代码示例// Cache First 策略 self.addEventListener(fetch, (event) { event.respondWith( caches.match(event.request) .then((response) { if (response) { return response; } return fetch(event.request) .then((response) { if (!response || response.status ! 200 || response.type ! basic) { return response; } const responseToCache response.clone(); caches.open(CACHE_NAME) .then((cache) { cache.put(event.request, responseToCache); }); return response; }); }) ); }); // Network First 策略 self.addEventListener(fetch, (event) { event.respondWith( fetch(event.request) .then((response) { if (!response || response.status ! 200 || response.type ! basic) { return caches.match(event.request); } const responseToCache response.clone(); caches.open(CACHE_NAME) .then((cache) { cache.put(event.request, responseToCache); }); return response; }) .catch(() { return caches.match(event.request); }) ); }); // Stale While Revalidate 策略 self.addEventListener(fetch, (event) { event.respondWith( caches.match(event.request) .then((response) { const fetchPromise fetch(event.request) .then((networkResponse) { if (!networkResponse || networkResponse.status ! 200 || networkResponse.type ! basic) { return networkResponse; } const responseToCache networkResponse.clone(); caches.open(CACHE_NAME) .then((cache) { cache.put(event.request, responseToCache); }); return networkResponse; }) .catch(() { return response; }); return response || fetchPromise; }) ); });五、前端缓存的注意事项1. 缓存失效问题缓存失效问题是前端缓存的一个常见问题。你必须确保缓存能够及时更新避免用户看到过期的内容。解决方案使用版本号或哈希值作为文件名的一部分使用协商缓存使用Service Worker的缓存策略2. 存储空间限制存储空间限制是前端缓存的另一个常见问题。不同的浏览器存储机制有不同的存储空间限制。解决方案合理使用不同的存储机制定期清理过期数据监控存储空间的使用情况3. 安全性问题安全性问题是前端缓存的一个重要问题。你必须确保缓存中的数据是安全的避免敏感信息泄露。解决方案不要在前端存储敏感信息使用HTTPS对存储的数据进行加密六、总结前端缓存是一个重要的前端主题它能够大大提高应用的性能和用户体验。作为一名前端工程师你必须掌握前端缓存的相关知识和工具确保你的应用能够快速响应。最后我想说缓存不是小事它关系到你的应用的性能和用户体验。别以为缓存只是后端的事情前端缓存同样重要。一个好的缓存策略能够让你的应用飞起来。作者cannonmonster01日期2026-04-04标签前端缓存、HTTP缓存、浏览器存储、Service Worker、缓存策略