多客户端Monorepo项目中Axios的管理方案咨询
Monorepo多客户端Axios管理方案
针对你的Monorepo场景,以下是几个落地性强的Axios管理思路,兼顾复用性与客户端隔离需求:
1. 抽离共享Axios核心包
在packages目录下新建axios-core包,统一管理基础配置与通用拦截逻辑,同时提供扩展能力让客户端定制自身逻辑:
核心实现示例
// packages/axios-core/src/index.ts import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; // 通用基础配置 const baseConfig: AxiosRequestConfig = { baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000, }; // 创建基础Axios实例 const baseAxios = axios.create(baseConfig); // 添加全局通用请求拦截器(如统一携带token) baseAxios.interceptors.request.use( (config) => { const token = localStorage.getItem('auth_token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }, (error) => Promise.reject(error) ); // 添加全局通用响应拦截器(如统一处理401跳转) baseAxios.interceptors.response.use( (res) => res, (error) => { if (error.response?.status === 401) window.location.href = '/login'; return Promise.reject(error); } ); // 提供客户端定制实例的创建函数 export function createClientAxios(customInterceptors?: { request?: Parameters<AxiosInstance['interceptors']['request']['use']>[0]; response?: Parameters<AxiosInstance['interceptors']['response']['use']>[0]; }): AxiosInstance { const clientAxios = baseAxios.create(); // 挂载客户端专属拦截器 if (customInterceptors?.request) { clientAxios.interceptors.request.use(customInterceptors.request); } if (customInterceptors?.response) { clientAxios.interceptors.response.use(customInterceptors.response); } return clientAxios; } // 导出基础实例供共享Composable使用 export default baseAxios;
2. 拦截器分层复用与定制
- 共享拦截器:所有通用逻辑(如token携带、通用错误码处理)放在
axios-core中,所有客户端默认继承。 - 客户端专属拦截器:每个客户端在自身代码中调用
createClientAxios方法添加专属逻辑,比如client1需要添加特定请求头、client2需要处理专属业务错误:
// apps/client1/composables/axios.ts import { createClientAxios } from '@monorepo/axios-core'; // 创建client1专属Axios实例 export const client1Axios = createClientAxios({ request: (config) => { config.headers['X-Client-Identifier'] = 'client1'; return config; }, response: (res) => { // 处理client1专属响应逻辑 if (res.data?.client1_feature_flag) { // 自定义业务处理 } return res; } });
3. Composable分层与构建隔离
分层管理
- 共享Composable:放在
packages/composables下,使用axios-core导出的基础实例调用共享API,比如getUser:
// packages/composables/user.composable.ts import baseAxios from '@monorepo/axios-core'; import type { IUser } from '@monorepo/models'; export async function getUser(): Promise<IUser> { const res = await baseAxios.get('/api/user/profile'); return res.data; }
- 客户端专属Composable:放在对应客户端的
composables目录下,使用客户端定制的Axios实例调用专属API,比如getClient1Data:
// apps/client1/composables/user.composable.ts import { client1Axios } from './axios'; export async function getClient1Data(): Promise<unknown> { const res = await client1Axios.get('/api/client1/exclusive-data'); return res.data; }
构建隔离保障
利用Monorepo构建工具的特性,确保客户端专属代码不会被其他客户端编译:
- 若使用Nx/Turbo:将每个客户端标记为独立项目,构建时仅处理当前项目的源码目录。
- 若使用Vite/Webpack:在客户端的配置文件中指定
root为自身目录(如apps/client1),或在tsconfig.json中排除其他客户端目录:
// apps/client1/tsconfig.json { "exclude": [ "../client2/**/*", "../client3/**/*", "node_modules" ] }
4. 类型统一管理
- 共享类型(如
IUser)继续放在packages/models下,供所有客户端与共享Composable引用。 - 客户端专属类型放在各自客户端的
models目录下,仅在当前客户端内部使用,避免跨客户端引用。
内容的提问来源于stack exchange,提问作者Jacek Kaczmarek
相关产品推荐
相关产品推荐

