首页
/ Axios 快速上手:多环境安装、模块导入与发起第一个请求(基于 v1.19 源码解析)

Axios 快速上手:多环境安装、模块导入与发起第一个请求(基于 v1.19 源码解析)

2026-09-04 21:46:50作者:吴年前Myrtle

本文基于 axios 仓库中的快速入门文档 first-steps.md(该页为西语版,中文社区可参考同结构英文页 first-steps.md)编写,系统讲解 axios 的完整安装方式(npm/pnpm/yarn/bun/deno 与 jsDelivr/unpkg CDN)、ESM/CJS 不同导入姿势背后的打包机制,以及如何用两行代码发起第一个 HTTP 请求。读完本文,你将掌握 axios 在浏览器与 Node.js 双环境下的接入方法,并能从 package.jsonlib/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-agentproxy-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.jsdist/esm/axios.js 等产物列在 package.jsonfiles 字段中,随 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.VERSIONaxios.AxiosErroraxios.isAxiosErroraxios.mergeConfigaxios.AxiosHeadersaxios.getAdapteraxios.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.jsonexports 映射一致:require 条件统一指向 ./dist/node/axios.cjspackage.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.jsonexports 字段把这两个路径作为子路径显式导出,保证它们可被直接 require,无需依赖条件解析。

5. 从源码结构看:环境是如何被选择的

package.jsonexports 按消费条件分派不同入口,这解释了“同一份 import axios from 'axios' 在不同运行时拿到不同实现”:

  • bundist/node/axios.cjs(require)/ index.js(ESM);
  • react-nativedist/browser/axios.cjs / dist/esm/axios.js
  • browserdist/browser/axios.cjs(require)/ index.js(ESM);
  • defaultdist/node/axios.cjs / index.js

同时 package.jsonbrowser 字段做了一层源码级替换:打包工具走 index.js(ESM 源码)时,会把 Node 专属模块替换掉——lib/adapters/http.js 被替换为 lib/helpers/null.jslib/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) 为例,调用链为:

  1. Axios.prototype.get 合并方法专属配置后调用 this.request()lib/core/Axios.js);
  2. _request() 中通过 mergeConfig(this.defaults, config) 把实例默认配置与单次请求配置合并(默认 method'get',见 lib/core/Axios.js);
  3. 请求拦截器链执行后交由 dispatchRequest,由适配器(http/xhr/fetch)真正发出请求,响应再经过响应拦截器链返回——整条链路均以 Promise 串联(lib/core/Axios.js)。

因此你拿到的 response 是统一的响应对象:response.data 为解析后的响应体,另有 statusheadersconfig 等字段,详见 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.isAxiosErrormoduleResolution 配置注意事项等)见 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());      // 查看当前环境选用的适配器

下一步建议按主题深入(均为仓库内文档):

本文所有结论均可在当前仓库中复核:安装字段见 package.json,导出结构见 index.jslib/axios.js,请求方法实现见 lib/core/Axios.js,方法级行为验证见 tests/smoke/cjs/tests/basic.smoke.test.cjs

登录后查看全文
热门项目推荐
相关项目推荐