Vue.js PWA开发:如何基于Axios实现HTTP请求离线缓存策略?
嘿,这个需求刚好是PWA的核心场景之一,结合Service Worker(SW)和一点Axios的封装就能完美实现,我给你一步步拆解:
核心实现思路
我们需要两种层面的配合:一是利用PWA的Service Worker拦截网络请求,实现「优先网络、失败 fallback 缓存」的全局策略;二是可以在Axios层面做本地缓存的补充,应对更灵活的业务场景。
1. 用Service Worker实现全局请求缓存拦截
Service Worker是PWA实现离线能力的核心,它可以在后台拦截所有网络请求,帮我们处理缓存逻辑。
编写Service Worker代码
创建service-worker.js文件放在项目根目录:
const CACHE_NAME = 'app-api-cache-v1'; // 缓存版本,更新时修改版本号即可清旧缓存 // 安装SW时预缓存必要资源(可选,比如你的接口地址可以提前加入) self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll([ // '/api/your-target-url' // 可选:预缓存目标接口 ])) ); }); // 拦截所有fetch请求,实现网络优先策略 self.addEventListener('fetch', (event) => { // 只处理我们需要的接口请求,避免拦截静态资源 if (event.request.url.includes('your-api-domain')) { event.respondWith( // 第一步:尝试网络请求 fetch(event.request) .then(networkRes => { // 网络请求成功,更新缓存 caches.open(CACHE_NAME).then(cache => { cache.put(event.request, networkRes.clone()); }); return networkRes; }) .catch(() => { // 网络失败,从缓存读取数据 return caches.match(event.request); }) ); } }); // 激活SW时清理旧缓存 self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.filter(name => name !== CACHE_NAME) .map(name => caches.delete(name)) ); }) ); });
在Vue项目中注册Service Worker
在main.js中加入注册逻辑:
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then(reg => console.log('Service Worker注册成功:', reg)) .catch(err => console.error('Service Worker注册失败:', err)); }); }
2. Axios层面的本地缓存补充(可选)
如果需要更细粒度的控制(比如给缓存加过期时间),可以封装Axios请求,结合localStorage做本地数据缓存:
// 封装带缓存的请求函数 async function fetchWithCache(url, callback) { try { // 优先发起网络请求 const res = await axios.get(url); // 把数据存入localStorage,带上时间戳 localStorage.setItem('app_cached_data', JSON.stringify({ data: res.data, timestamp: Date.now() })); callback(res.data); } catch (err) { // 网络失败,读取本地缓存 const cachedStr = localStorage.getItem('app_cached_data'); if (cachedStr) { const cachedObj = JSON.parse(cachedStr); // 可选:判断缓存是否过期(比如7天有效期) const isExpired = Date.now() - cachedObj.timestamp > 7 * 24 * 60 * 60 * 1000; if (!isExpired) { callback(cachedObj.data); return; } } // 无缓存或缓存过期时的错误处理 console.error('无网络连接且无有效缓存'); callback(null); } } // 使用示例 const targetUrl = '你的接口地址'; fetchWithCache(targetUrl, (data) => { if (data) { // 处理获取到的数据(不管是网络还是缓存来的) console.log('拿到数据:', data); } });
3. Vue CLI项目的简化方案
如果你的项目是用Vue CLI创建的,直接使用@vue/cli-plugin-pwa插件可以省去手动写SW的麻烦,只需要在vue.config.js中配置缓存策略:
module.exports = { pwa: { workboxOptions: { runtimeCaching: [ { // 匹配你的接口地址 urlPattern: /^https:\/\/your-api-domain\/.*/, // 采用「网络优先」策略,符合你的需求 handler: 'NetworkFirst', options: { cacheName: 'api-cache', // 只缓存200状态的响应 cacheableResponse: { statuses: [0, 200] } } } ] } } };
内容的提问来源于stack exchange,提问作者H. K.
相关产品推荐
相关产品推荐

