npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

longmo-plugin-axios

v2.0.4

Published

基于 `axios-cache-interceptor` 增强的 axios 插件(见 `./llms-full.txt` ),提供开箱即用的缓存、错误处理、loading 等功能。

Readme

longmo-plugin-axios

基于 axios-cache-interceptor 增强的 axios 插件(见 ./llms-full.txt ),提供开箱即用的缓存、错误处理、loading 等功能。

支持 axios-cache-interceptor 1.x 版本

注意:如果使用 Web Storage(localStorage/sessionStorage),无需额外依赖。如果使用其他存储类型,请按需安装:

# 使用 IndexedDB 存储(可选)
pnpm add localforage@^1.10.0

# 使用内存存储的 LRU 策略(可选,已内置)
pnpm add lru-cache@^11.2.4

快速使用

使用 setup 返回一个平台的 axios 最佳实践配置,并提供钩子函数进行自定义。

import { setup } from 'longmo-plugin-axios'

const _axios = setup({}) // 返回 axios 实例,用法见 axios 的文档
export default _axios

setup

配置了接口的通用错误处理能力

返回axios实例,使用默认配置可快速使用,简化配置,不和任何框架绑定,适用所有平台的UI框架

在业务平台可快速使用, 注意重复setup都会返回一个新的axios实例,可全局注册复用实例

如果setup不能满足项目需求,可自行使用axios配置,配置说明见上。

基础使用

import { setup } from 'longmo-plugin-axios'

const _axios = setup()
export default _axios

高级使用

  • loading.js全局loading配置
import {Loading} from 'element-ui'

export default {
  instance: null,
  show() {
    this.instance = Loading.service({fullscreen: true, lock: true, background: 'rgba(255, 255, 255, 0.2)'})
  },
  hide() {
    if (this.instance) {
      this.instance.close()
    }
  }
}
  • plugins/axios.js 配置
import loading from './loading.js'
import { Notification } from 'element-ui'
import { setup } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 3 * 60 * 1000, // 缓存有效期 3 分钟
  },
  loading: loading,
  errorAction: (error) => {
    Notification.error({
      title: error.name, // 如果不想使用默认标题,可通过 error.type 判断设置
      message: error.message
    })
  },
  authFailAction: () => {
    // logout 返回到登录页面逻辑
  }
})
export default _axios
  • 请求使用参数
import axios from './plugins/axios.js'

axios.get('/user')

axios.get('/list', {
  manual: true, // 手动处理报文,不用默认方式处理
  loading: true, // 请求时显示网络请求 loading,前提是在 setup 设置了 loading
})

setupOptions

// setup 配置参数
export type SetupConfig = {
  cache?: CacheOptions, // 缓存配置,详见 axios-cache-interceptor 文档
  loading?: IAxiosLoading, // 全局 loading 配置,默认不显示,需要在每个请求中设置
  authFailAction?(error: any): void, // 认证失败调用的函数,可在这里处理跳转逻辑
  errorAction?(error: IError): void, // 网络请求失败错误处理逻辑
  requestInterceptor?(config: TCInternalCacheRequestConfig): TCInternalCacheRequestConfig, // 自定义请求拦截器
  responseInterceptor?(response: any): any, // 自定义响应拦截器
}

// 网络请求 全局loading,和UI框架解耦
export interface IAxiosLoading {
  instance: any;

  show(): void;

  hide(): void;
}

// 网络请求错误类型
export enum IErrorType {
  NETWORK = 'NETWORK', // 网络异常 404 500
  SYSTEM = 'SYSTEM' // 系统异常 response.status=200, 系统报错
}

// 异常接口
export interface IError extends Error {
  name: string; // 网络异常 系统异常
  message: string; // 错误信息
  type: IErrorType; // 异常类型
  code: string | number // 错误码,网络异常错误码 系统异常错误码
}

use(可选)

用于在 Vue 应用中挂载全局 $axios 实例。

  • Vue 2:挂载到 Vue.prototype

    import Vue from 'vue'
    import { setup, use } from 'longmo-plugin-axios'
    
    use(setup(), Vue)
  • Vue 3:挂载到 app.config.globalProperties

    import { createApp } from 'vue'
    import App from './App.vue'
    import { setup, use } from 'longmo-plugin-axios'
    
    const app = createApp(App)
    use(setup({}), app)
    app.mount('#app')
  • 使用挂载的全局 $axios 实例

    {
      mounted() {
        this.$axios.get('/user')
      }
    }

缓存配置

本项目基于 axios-cache-interceptor 实现缓存功能,支持多种存储策略和缓存配置。

支持的存储类型

axios-cache-interceptor 内置了以下存储类型:

  1. Memory Storage(默认):内存存储,适用于所有环境,页面刷新后数据丢失
  2. Web Storage API:浏览器本地存储(localStorage/sessionStorage),持久化缓存
  3. 自定义存储:可以通过 buildStorage 创建自定义存储(如 IndexedDB、Redis 等)

使用 localStorage 示例

import { setup, buildWebStorage } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 5 * 60 * 1000, // 缓存有效期 5 分钟
    storage: buildWebStorage(localStorage, 'axios-cache:')
  }
})

使用 sessionStorage 示例

import { setup, buildWebStorage } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 5 * 60 * 1000,
    storage: buildWebStorage(sessionStorage, 'axios-cache:')
  }
})

使用 IndexedDB 示例(需要安装 localforage)

import { setup, buildStorage } from 'longmo-plugin-axios'
import localforage from 'localforage'

// 创建 IndexedDB 实例
const forageStore = localforage.createInstance({
  driver: [localforage.INDEXEDDB, localforage.LOCALSTORAGE],
  name: 'my-app-cache',
  storeName: 'axios_cache'
})

// 构建自定义存储
const indexedDbStorage = buildStorage({
  async set(key, value) {
    await forageStore.setItem(key, value)
  },
  async find(key) {
    return (await forageStore.getItem(key)) ?? undefined
  },
  async remove(key) {
    await forageStore.removeItem(key)
  },
  async clear() {
    await forageStore.clear()
  }
})

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 5 * 60 * 1000,
    storage: indexedDbStorage
  }
})

自定义存储说明

您可以通过 buildStorage 函数创建任意类型的存储,只需实现以下接口:

interface StorageAdapter {
  // 保存数据
  set(key: string, value: any, currentRequest?: any): void | Promise<void>

  // 查找数据
  find(key: string, currentRequest?: any): any | Promise<any | undefined>

  // 删除数据
  remove(key: string, currentRequest?: any): void | Promise<void>

  // 清空所有数据(可选)
  clear?(): void | Promise<void>
}

常见的自定义存储场景:

  • IndexedDB:适合大量数据缓存,容量大(通常 50MB+)
  • Redis:服务端缓存,多实例共享
  • Memory + LRU:内存受限环境,自动淘汰旧数据
  • FileSystem:Node.js 环境持久化缓存

更多关于存储的信息请参考:Storages

基础使用

import { setup } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 5 * 60 * 1000, // 缓存有效期(毫秒)
  }
})

_axios.get('https://httpbin.org/get') // 发起真实网络请求
_axios.get('https://httpbin.org/get') // 使用前一个请求的缓存,不发出实际的 HTTP 请求

高级使用

import { applyInterceptors } from '@/api/setupAxiosInterceptors';
import { buildStorage, buildStringKeyGenerator, forageStorage, setup } from 'longmo-plugin-axios';

const cacheOptions = {
  enabled: true,
  methods: ['get', 'head', 'post'], // 支持缓存 post 请求
  ttl: 60 * 1000, // 设置缓存有效期毫秒值
  storage: buildStorage(forageStorage),
  generateKey: buildStringKeyGenerator(),
  // 必须设置为false,否则预检请求会报错
  cacheTakeover: false
};

export function getCacheAxios(domain = '/') {
  const axiosOptions = {
    baseURL: domain,
    'Content-Type': 'application/json;charset=UTF-8'
  };
  const http = setup({
    ...axiosOptions,
    cache: cacheOptions
  });
  applyInterceptors(http);
  return http;
}

覆盖实例的配置参数

在使用特定的缓存配置设置了 axios-cache-interceptor 之后,您可以在单个请求中覆盖该配置。

对时效性要求比较高的接口,可以在请求中禁用缓存,设置 cache.enabled = false

import { setup } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    ttl: 5 * 60 * 1000, // 设置缓存有效期(毫秒)
  }
})

// 设置该请求的缓存有效时间(毫秒)
_axios.get('https://httpbin.org/get', {
  cache: {
    ttl: 2 * 60 * 1000
  }
})

// 手动禁用缓存,并调用真实的 HTTP 请求
_axios.get('https://httpbin.org/get', {
  cache: {
    enabled: false
  }
})

CacheOptions 配置说明

更多高级设置参数,请查看 axios-cache-interceptor 官方文档

{
  /**
   * 是否启用缓存
   * @default true
   */
  enabled?: boolean;

  /**
   * 缓存生存时间(毫秒)
   * 可以是固定值或函数,函数接收响应对象并返回 TTL 值
   * @default 1000 * 60 * 5 (5分钟)
   */
  ttl?: number | ((response: CacheAxiosResponse) => number | Promise<number>);

  /**
   * 是否从响应头解析缓存时间(Cache-Control、Age 等)
   * 如果启用,ttl 将作为兜底值,优先使用服务器返回的缓存头
   * @default true
   */
  interpretHeader?: boolean;

  /**
   * 防止浏览器双重缓存
   * 会在请求中添加 Cache-Control、Pragma、Expires 头,阻止浏览器缓存
   * @default true
   */
  cacheTakeover?: boolean;

  /**
   * 允许缓存的 HTTP 方法
   * @default ['get', 'head']
   */
  methods?: Method[];

  /**
   * 缓存谓词,用于判断响应是否可以被缓存
   */
  cachePredicate?: CachePredicate;

  /**
   * 缓存更新策略,用于在请求成功后更新其他缓存
   */
  update?: CacheUpdater;

  /**
   * ETag 缓存支持
   * @default true
   */
  etag?: boolean | string;

  /**
   * If-Modified-Since 缓存支持
   * @default true
   */
  modifiedSince?: boolean;

  /**
   * 错误时使用缓存(stale-if-error)
   * @default true
   */
  staleIfError?: boolean | number | StaleIfErrorPredicate;

  /**
   * 强制发起新请求,绕过缓存检查
   * @default false
   */
  override?: boolean;

  /**
   * Vary 头处理
   * @default true
   */
  vary?: boolean | string[];

  /**
   * 水合回调,当需要从网络获取数据但存在过期缓存时调用
   * 可用于先展示旧数据,再更新为新数据
   */
  hydrate?: (cache: StorageValue) => void | Promise<void>;
}

调试模式

开启调试模式可以帮助您了解缓存的工作机制,排查问题。

import { setup } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    debug: console.log, // 打印调试信息到控制台
    ttl: 5 * 60 * 1000
  }
})

调试信息包括:

  • 请求是否命中缓存
  • 缓存的 TTL 信息
  • 并发请求的处理
  • 缓存的读写操作

详细调试指南请参考:Debugging

注意事项

Axios 拦截器执行顺序

Axios 拦截器对请求和响应的执行顺序不同:

  • 请求拦截器按相反顺序执行——最后添加的拦截器最先运行(LIFO - 后进先出)
  • 响应拦截器按正常顺序执行——第一个添加的拦截器首先运行(FIFO - 先进先出)
// 这个将在缓存拦截器之前运行
axios.interceptors.request.use((req) => req);

// 这个将在缓存拦截器之后运行
axios.interceptors.response.use((res) => res);

setupCache(axios);

// 这个将在缓存拦截器之后运行
axios.interceptors.request.use((req) => req);

// 这个将在缓存拦截器之前运行
axios.interceptors.response.use((res) => res);

如果需要完全控制拦截器的注册顺序,可以使用 register: false 选项手动注册:

import { setupCache } from 'axios-cache-interceptor';

const axios = setupCache(Axios.create(), { register: false });

// 先注册自己的拦截器
axios.interceptors.request.use((req) => req);
axios.interceptors.response.use((res) => res);

// 再手动注册缓存拦截器
axios.interceptors.request.use(
  axios.requestInterceptor.onFulfilled,
  axios.requestInterceptor.onRejected
);
axios.interceptors.response.use(
  axios.responseInterceptor.onFulfilled,
  axios.responseInterceptor.onRejected
);

扩展类型

使用 longmo-plugin-axios 时,你会注意到它的类型与默认的 AxiosInstanceAxiosRequestConfigAxiosResponse 不同。

这是因为我们选择覆盖 Axios 的接口,而不是扩展,以避免与其他库的兼容性问题。

然而,这也意味着在与其他包集成或创建自定义拦截器时,你需要覆盖/扩展我们自己的类型,

TCAxiosInstanceTCAxiosRequestConfigTCAxiosResponse,以符合你的需求。

具体步骤如下:

declare module 'longmo-plugin-axios' {
  interface TCAxiosRequestConfig<R = unknown, D = unknown> {
    customProperty: string;
  }
}

流与非 JSON 响应

axios-cache-interceptor 只能处理可序列化的数据类型。如果你需要缓存流或缓冲区,需要使用 transformResponse 将其转换为字符串或对象。

import { setup } from 'longmo-plugin-axios'

const _axios = setup({
  cache: { enabled: true }
})

const response = await _axios.get('my-url-that-returns-a-stream', {
  responseType: 'stream',
  transformResponse(response) {
    // 你需要实现这个转换函数
    return convertStreamToStringOrObject(response.data)
  }
})

response.data // 将是字符串或对象,可以被缓存

如果仍然需要 response.data 作为流或缓冲区,就需要手动缓存。

清除缓存

// 清除特定请求的缓存
await _axios.storage.remove(requestId)

// 清除所有缓存
await _axios.storage.clear()

例如,在用户退出登录时清除所有缓存:

function logout() {
  // 清除 token 等操作...

  // 清除所有缓存
  _axios.storage.clear()

  // 跳转到登录页
}

自定义缓存 Key

buildKeyGenerator 方法接收 axiosConfig 作为参数,

返回值若是对象,则使用 hash 进行转换;若是字符串或者数字,统一转为字符串作为 key。

import { setup, buildKeyGenerator, buildURLWithAxiosConfig } from 'longmo-plugin-axios'

const _axios = setup({
  cache: {
    enabled: true,
    debug: console.error,
    generateKey: buildKeyGenerator((request) =>
      buildURLWithAxiosConfig(request)
    ),
    ttl: 1000 * 2, // 过期时间 2 秒
  }
})

export default _axios

更多关于 Request ID 的信息请参考:Request ID

TTL(Time To Live)说明

ttlTime To Live(生存时间) 的缩写,它决定了 缓存条目在内存中可以保留多久(单位:毫秒)

| 配置项 | 作用 | |-------------------------|------------------------------------------------------------------| | ttl: 99999 | 默认缓存有效期为 99,999 毫秒(约 100 秒) | | interpretHeader: true | 优先从 HTTP 响应头(如 Cache-ControlAge)中解析真实的缓存时间,而不是直接用 ttl |

🧠 interpretHeader: true 时的逻辑(重点!)

interpretHeadertrue(默认值),ttl 只是"兜底值",实际 TTL 会根据服务器返回的 HTTP 缓存头动态计算:

  1. 服务器返回:
    Cache-Control: max-age=300
    Age: 50
  2. 那么实际缓存时间 = max-age - Age = 300 - 50 = 250 秒
  3. 这个 250 秒会覆盖你设置的 ttl: 99999
  4. 所以你在日志中看到:
    log(`Cache TTL info: ${cacheInformation.ttl}`)
    // 输出的是 250000(毫秒),不是 99999!

📌 总结:ttl 的作用

| 场景 | ttl 的作用 | |-----------------------------|--------------------------------------| | interpretHeader: true(默认) | 备用值:当服务器没返回有效缓存头时才用 | | interpretHeader: false | 强制使用:所有请求都按这个时间缓存 | | 单位 | 毫秒(ms) | | 默认值 | 如果不传 ttl,默认是 1000 * 60 * 5(5 分钟) |

缓存失效策略

当数据发生变化时(如创建、更新、删除操作),需要使相关缓存失效。

方法一:编程式更新缓存

// 使用自定义 ID 标识请求
function listPosts() {
  return _axios.get('/posts', {
    id: 'list-posts'
  })
}

function createPost(data) {
  return _axios.post('/posts', data, {
    cache: {
      update: {
        // 在创建新文章后,更新列表缓存
        'list-posts': (listPostsCache, createPostResponse) => {
          if (listPostsCache.state !== 'cached') {
            return 'ignore'
          }

          // 将新文章添加到列表
          listPostsCache.data.posts.push(createPostResponse.data)

          return listPostsCache
        }
      }
    }
  })
}

方法二:删除缓存

function createPost(data) {
  return _axios.post('/posts', data, {
    cache: {
      update: {
        // 直接删除列表缓存,下次请求时会重新从服务器获取
        'list-posts': 'delete'
      }
    }
  })
}

方法三:手动清除缓存

// 清除特定请求的缓存
await _axios.storage.remove('list-posts')

// 清除所有缓存
await _axios.storage.clear()

更多关于缓存失效的信息请参考:Invalidating Cache

响应对象属性

使用 axios-cache-interceptor 后,响应对象会包含以下额外属性:

const response = await _axios.get('/api/data', {
  id: 'my-request-id'
})

response.id      // 请求 ID,用于缓存键
response.cached  // boolean,表示是否来自缓存
response.stale   // boolean,表示是否是过期缓存

TODO

  • [x] 默认关闭适配器
  • [ ] 添加重试适配器
  • [x] 抽离默认拦截器适配器
  • [x] 升级 lru-cache 版本
  • [x] 支持清除所有缓存方法(例如退出登录时需要清除所有缓存)
  • [x] 支持检查响应是否是来自缓存
  • [x] 支持强制更新某个接口的缓存
  • [x] 添加缓存 key 自定义生成规则配置项
    • 支持 GET 请求时添加缓存,PUT、PATCH、DELETE 请求时,使相同 URL 的缓存失效