导出代理是通过在模块导出层动态拦截或重导出来实现新旧API无感兼容的技术。它利用Proxy或具名重导出(如export { getUser as fetchUser })保持旧接口签名,避免修改调用方、运行时判断或破坏tree-shaking,需同步维护TS类型并规避循环依赖。

导出代理(Export Proxying)是一种在模块加载阶段动态拦截和重写导出对象的技术,它能让新模块“假装”提供旧 API 的接口,而实际调用的是重构后的新逻辑。这种方式无需修改调用方代码,也不需要运行时条件判断,真正实现对遗留 API 的无感兼容。
核心思路:在模块导出层做透明桥接
关键不是改调用方,也不是硬编码兼容逻辑,而是让模块的 export 表现得和旧版完全一致——包括函数名、参数签名、返回值类型甚至错误行为。本质是用 Proxy 或静态重导出封装一层“外观”。
- 对 ESM 模块,可在入口文件中用
export { ... } from 'new-module'显式重导出,或用export * as oldApi from 'new-module'+ 默认导出补全 - 若需运行时控制(如根据环境切换实现),可用
export default new Proxy({}, handler)动态拦截属性访问 - 注意:TypeScript 类型需同步维护,建议用
declare module或export type复用旧类型定义,避免类型断裂
常见场景与具体做法
比如旧模块导出 fetchUser(id),新模块已改为 getUser({ id }) 且增加了鉴权逻辑:
- 新建兼容层
legacy-api.js:import { getUser } from './modern-api.js';<br>export const fetchUser = (id) => getUser({ id });<br>export default { fetchUser }; - 让原有构建工具(如 Vite、Webpack)将
import * as api from 'legacy-api'解析到该文件,而非真实旧包 - 若旧 API 有副作用(如全局注册、默认配置),需在代理模块顶部执行一次初始化,确保行为一致
规避陷阱:命名冲突与树摇风险
直接重导出会丢失原始模块的副作用和命名空间语义,尤其影响 tree-shaking 和调试体验:
- 避免
export * from 'modern-module'—— 它会暴露所有新 API,破坏封装边界 - 使用具名重导出(
export { getUser as fetchUser })更安全,且支持 IDE 跳转和类型推导 - 若旧模块导出为
default对象,新模块也应导出default,并确保其属性可枚举、可遍历,否则for...in等操作会失效
进阶:配合打包工具自动注入
当项目中存在大量遗留引用时,手动改 import 不现实。可通过插件实现自动化代理:
- Vite 插件中使用
resolveId拦截对legacy-pkg的请求,返回虚拟模块路径 - Rollup/webpack 的 alias 配置可映射旧包名为代理模块,但需确保解析顺序优先于 node_modules
- 注意循环依赖:代理模块不应再导入旧包,所有逻辑必须来自新实现,否则无法解耦
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











