Axios 快速上手:多环境安装、模块导入与发起第一个请求(基于 v1.19 源码解析)
本文基于 axios 仓库中的快速入门文档 first-steps.md(该页为西语版,中文社区可参考同结构英文页 first-steps.md)编写,系统讲解 axios 的完整安装方式(npm/pnpm/yarn/bun/deno 与 jsDelivr/unpkg CDN)、ESM/CJS 不同导入姿势背后的打包机制,以及如何用两行代码发起第一个 HTTP 请求。读完本文,你将掌握 axios 在浏览器与 Node.js 双环境下的接入方法,并能从 package.json 与 lib/axios.js 等源码印证每一条结论。
一、安装 axios
axios 的安装方式分为两类:包管理器安装(推荐,便于参与 tree-shaking 与模块解析)和 CDN 直接引入(适合快速原型或无构建环境)。
1. 包管理器安装
| 包管理器 | 安装命令 |
|---|---|
| npm | npm install axios |
| pnpm | pnpm install axios |
| yarn | yarn add axios |
| bun | bun add axios |
| deno | deno install npm:axios |
从 package.json 可以看到,axios 运行时仅依赖 4 个生产依赖:follow-redirects(重定向处理)、form-data(multipart 表单)、https-proxy-agent 与 proxy-from-env(Node 环境下的代理支持),因此任何支持 ES Modules 的环境都能直接安装使用。
2. 通过 jsDelivr / unpkg 引入
在 package.json 中,axios 显式声明了两个 CDN 入口字段:
"jsdelivr": "dist/axios.min.js",
"unpkg": "dist/axios.min.js",
这意味着 jsDelivr 与 unpkg 的默认入口就是压缩后的浏览器全局构建。官方文档给出的引入方式是:
<!-- jsDelivr:建议锁定版本号 <x.x.x> -->
<script src="https://cdn.jsdelivr.net/npm/axios@<x.x.x>/dist/axios.min.js"></script>
<!-- unpkg:同样建议锁定版本号 <x.x.x> -->
<script src="https://unpkg.com/axios@<x.x.x>/dist/axios.min.js"></script>
文档特别提醒:生产环境务必使用 minified 版本并固定版本号,省略版本号(跟随 latest)虽可行,但可能引入未经测试的行为变更,官方强烈不推荐用于生产。引入后全局 axios 对象即可直接使用。
适用前提:仓库当前版本为 1.19.0(见 package.json)。
dist/axios.min.js、dist/esm/axios.js等产物列在 package.json 的files字段中,随 npm 包一起发布,故 CDN 上可稳定取到对应版本。
二、导入 axios:ESM 命名导出、require 与预构建 bundle
安装完成后,导入方式取决于你的模块系统。以下小节完整覆盖入门文档给出的全部姿势,并给出源码级依据。
1. ESM:命名导出与默认导出
// 命名导出:isCancel、AxiosError 等都是从 axios 工厂上“再导出”的成员
import axios, { isCancel, AxiosError } from "axios";
// 也可以只用默认导出,静态成员都挂在默认导出上
import axios from "axios";
console.log(axios.isCancel("something"));
这条“命名导出只是工厂再导出”的说法可以在源码中找到直接证据。index.js 从 ./lib/axios.js 拿到默认导出的 axios 实例,再把其静态属性拆成顶层命名导出:
// index.js(节选)
const {
Axios,
AxiosError,
CanceledError,
isCancel,
CancelToken,
VERSION,
all,
Cancel,
isAxiosError,
spread,
toFormData,
AxiosHeaders,
HttpStatusCode,
formToJSON,
getAdapter,
mergeConfig,
create,
} = axios;
export { axios as default, create, Axios, AxiosError, CanceledError, /* ... */ };
而这些静态属性则是在 lib/axios.js 中通过 createInstance(defaults) 创建默认实例后逐个挂载的:axios.Axios(允许继承)、axios.CanceledError / axios.CancelToken / axios.isCancel(取消机制)、axios.VERSION、axios.AxiosError、axios.isAxiosError、axios.mergeConfig、axios.AxiosHeaders、axios.getAdapter、axios.HttpStatusCode 等。文件末尾注释 // this module should only have a default export 点明了设计原则:底层模块只暴露默认导出,顶层 index.js 负责将其“摊平”为命名导出,从而保证 ESM 与 CJS 两种消费方式行为一致。
2. CommonJS:仅默认导出
const axios = require("axios");
console.log(axios.isCancel("something"));
使用 require 时只有默认导出可用,不存在 CJS 命名解构。这与 package.json 的 exports 映射一致:require 条件统一指向 ./dist/node/axios.cjs(package.json),即预构建的 CommonJS bundle,其顶层就是整个 axios 工厂对象。
3. 兼容某些 ES6 bundler/linter 的写法
个别打包器或 linter 对默认导出的 interop 处理不一致,此时可使用:
import { default as axios } from "axios";
4. 直接引用预构建 bundle(模块解析异常的遗留环境)
const axios = require("axios/dist/browser/axios.cjs"); // 浏览器 CommonJS bundle(ES2017)
// const axios = require("axios/dist/node/axios.cjs"); // Node CommonJS bundle(ES2017)
package.json 的 exports 字段把这两个路径作为子路径显式导出,保证它们可被直接 require,无需依赖条件解析。
5. 从源码结构看:环境是如何被选择的
package.json 的 exports 按消费条件分派不同入口,这解释了“同一份 import axios from 'axios' 在不同运行时拿到不同实现”:
bun→dist/node/axios.cjs(require)/index.js(ESM);react-native→dist/browser/axios.cjs/dist/esm/axios.js;browser→dist/browser/axios.cjs(require)/index.js(ESM);default→dist/node/axios.cjs/index.js。
同时 package.json 的 browser 字段做了一层源码级替换:打包工具走 index.js(ESM 源码)时,会把 Node 专属模块替换掉——lib/adapters/http.js 被替换为 lib/helpers/null.js,lib/platform/node/index.js 被替换为 lib/platform/browser/index.js。可以推断:axios 在编译期通过“browser 字段别名”剔除了 Node 的 http 适配器,运行时再通过适配器工厂选择 xhr/fetch,实现浏览器与 Node 的共用源码。适配器入口位于 lib/adapters/adapters.js,具体实现分别在 lib/adapters/http.js(Node)、lib/adapters/xhr.js(浏览器 XHR)与 lib/adapters/fetch.js(Fetch)。
三、发起第一个请求
入门文档的核心结论:一个 axios 请求只需要两行代码——指定 URL 与方法即可。以下是对 JSONPlaceholder 公共 API 的 GET 请求示例:
import axios from "axios";
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
1. 请求方法家族:get/post/request 从哪来
文档说“可以用 axios.get 发 GET、axios.post 发 POST,也可以用 axios.request 发任意方法”。这些方法的真实定义在 lib/core/Axios.js:
// 无请求体的方法:delete / get / head / options
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
Axios.prototype[method] = function (url, config) {
return this.request(mergeConfig(config || {}, { method, url, /* ... */ }));
};
});
// 带请求体的方法:post / put / patch / query(并派生 postForm/putForm/patchForm)
utils.forEach(['post', 'put', 'patch', 'query'], function forEachMethodWithData(method) {
Axios.prototype[method] = generateHTTPMethod();
if (method !== 'query') {
Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
}
});
从源码结构看有两点值得注意:
- 所有便捷方法最终都收敛到
Axios.prototype.request,即方法别名只是对request()的薄封装,request()始终可用且是最通用的入口; - 除了常见动词外,
query(无 multipart 变体)也被注册为方法,postForm/putForm/patchForm则是自动附加Content-Type: multipart/form-data的表单快捷方式。
这些方法可用性在冒烟测试 tests/smoke/cjs/tests/basic.smoke.test.cjs 中有逐项验证:axios(url)、get()、delete()、head()、options()、post()、put()、patch() 均被断言为正确的 HTTP 方法与路径。其中“axios(url, config) 直接可调用”这一 fetch 风格用法,其支持逻辑在 lib/core/Axios.js:当第一个参数是字符串时,会被包装为 { url } 配置对象。
2. 请求的底层链路(简述)
以 axios.get(url) 为例,调用链为:
Axios.prototype.get合并方法专属配置后调用this.request()(lib/core/Axios.js);_request()中通过mergeConfig(this.defaults, config)把实例默认配置与单次请求配置合并(默认method为'get',见 lib/core/Axios.js);- 请求拦截器链执行后交由
dispatchRequest,由适配器(http/xhr/fetch)真正发出请求,响应再经过响应拦截器链返回——整条链路均以 Promise 串联(lib/core/Axios.js)。
因此你拿到的 response 是统一的响应对象:response.data 为解析后的响应体,另有 status、headers、config 等字段,详见 response-schema.md。
3. 生产环境务必设置 timeout(重要提示)
入门文档特别给出的生产环境提示:没有 timeout 的挂起请求可能无限期卡死。请在请求配置中显式设置:
const response = await axios.get("https://example.com/data", {
timeout: 5000, // 5 秒
});
对照 request-config.md 的定义:timeout 是请求超时前的毫秒数,超过该时长请求会被中止。超时后会抛出 ECONNABORTED / ETIMEDOUT 错误码,具体捕获方式参见 error-handling.md。
四、更完整的实战用法:then/catch 与 async/await
入门页之外,仓库自带的示例文档 examples/commonjs.md 给出了一套可直接复制的用法模板,两种风格都值得掌握:
1. Promise 链式风格(then/catch/finally)
axios
.get("https://jsonplaceholder.typicode.com/posts", {
params: { postId: 5 },
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
2. async/await 风格(推荐,避免回调嵌套)
const createPost = async () => {
try {
const response = await axios.post(
"https://jsonplaceholder.typicode.com/posts",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
该文档同样提供了 get/put/patch/delete 的完整 async/await 示例,注意示例中 params 用于在 URL 上追加查询串(由 buildURL 实现)。
3. TypeScript 项目中的第一步
axios 随包附带类型定义(index.d.ts 与 CJS 版 index.d.cts)。最小可用的 TS 起步姿势:
import axios from "axios";
import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
// 用泛型参数声明响应数据结构
const response = await axios.get<Post>("https://jsonplaceholder.typicode.com/posts/1");
console.log(response.data.title); // TypeScript 知道这是 string
完整的类型标注(请求体类型、错误收窄 axios.isAxiosError、moduleResolution 配置注意事项等)见 examples/typescript.md 与专题页 type-script.md。
五、小结与下一步
按本文步骤,你已经完成了:选择正确的安装渠道(包管理器或锁定版本的 CDN)、按模块系统选择导入方式(ESM 命名导出 / require 默认导出 / 预构建 bundle)、发出第一个 GET 请求,并理解了 timeout 这一生产必备配置。快速验证安装的三个小信号:
console.log(axios.VERSION); // 当前仓库版本为 1.19.0
console.log(axios.Axios); // 可用于继承的 Axios 类
console.log(axios.getAdapter()); // 查看当前环境选用的适配器
下一步建议按主题深入(均为仓库内文档):
- features.md:axios 的核心特性全景;
- request-config.md:完整请求配置(含
timeout、baseURL、headers等); - error-handling.md:错误分类与
ECONNABORTED/ETIMEDOUT处理; - interceptors.md:请求/响应拦截器;
- create-an-instance.md:创建带
baseURL等默认值的独立实例。
本文所有结论均可在当前仓库中复核:安装字段见 package.json,导出结构见 index.js 与 lib/axios.js,请求方法实现见 lib/core/Axios.js,方法级行为验证见 tests/smoke/cjs/tests/basic.smoke.test.cjs。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00