Node.js Blog
Axios 到 WHATWG Fetch 的迁移
8.5Score
TL;DR · AI 摘要
Node.js 推荐从 Axios 迁移到 WHATWG Fetch API,以提升性能和安全性。
核心要点
- Fetch API 是 Node.js 原生支持的网络请求接口,无需额外依赖。
- 迁移到 Fetch 可提高代码标准兼容性并减少安全风险。
- Node.js v18.0.0 或更高版本支持 Fetch API,v21.0.0 后稳定可用。
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- Axios to WHATWG Fetch Migration
- Migration Reasons
- Native Support
- Performance Improvement
- Standards Compliance
- Security Enhancement
- Version Requirements
- Node.js v18.0.0 or later
- Node.js v21.0.0 or later
- Supported Methods
- axios.request
- axios.get
- axios.post
- axios.put
- axios.delete
金句 / Highlights
值得收藏与分享的关键句。
Fetch 是 Node.js 原生支持的网络请求接口,无需额外依赖。
Fetch 遵循 Web 标准,使编写跨平台代码更容易。
Node.js v18.0.0 或更高版本支持 Fetch API。
#Node.js#Fetch API#Axios#迁移
打开原文AugustinMauroy
[从 Axios 迁移到 WHATWG Fetch](https://nodejs.org/en/blog/migrations/axios-to-fetch#migrate-from-axios-to-whatwg-fetch)
此代码转换工具可将使用 Axios 的代码转换为利用 WHATWG Fetch API 的代码,该 API 现已原生支持 Node.js。
[为何要迁移?](https://nodejs.org/en/blog/migrations/axios-to-fetch#why-doing-this)
- 原生支持:Fetch 已内置在 Node.js 中,无需外部库及其相关的维护负担。
- 性能提升:Fetch 针对现代 JavaScript 运行时进行了优化,通常比 Axios 性能更优。
- 更好的标准兼容性:Fetch 严格遵循 Web 标准,使得编写跨平台代码(同时适用于 Node.js 和浏览器)更加容易。
- 降低安全风险:移除 Axios 可消除与第三方依赖相关的潜在漏洞,增强应用程序的安全性。
[Node.js 版本要求](https://nodejs.org/en/blog/migrations/axios-to-fetch#nodejs-version-requirements)
- Node.js v18.0.0 或更高版本(Fetch API 可用,但标记为实验性)
- Node.js v21.0.0 或更高版本(Fetch API 已稳定)
如果你的包当前支持早于 v18.0.0 的 Node.js 版本,则在不放弃对这些版本支持的情况下无法迁移到 Fetch API。这需要将包的主版本号升级,并更新 package.json 中的 engines 字段,要求 Node.js >= v18.0.0。
[支持的转换](https://nodejs.org/en/blog/migrations/axios-to-fetch#supported-transformations)
代码转换工具支持以下 Axios 方法,并将其转换为对应的 Fetch 等效方法:
axios.request(config)axios.get(url[, config])axios.delete(url[, config])axios.head(url[, config])axios.options(url[, config])axios.post(url[, data[, config]])axios.put(url[, data[, config]])axios.patch(url[, data[, config]])axios.postForm(url[, data[, config]])axios.putForm(url[, data[, config]])axios.patchForm(url[, data[, config]])
[示例](https://nodejs.org/en/blog/migrations/axios-to-fetch#examples)
[GET 请求](https://nodejs.org/en/blog/migrations/axios-to-fetch#get-request)
code
const base = 'https://dummyjson.com/todos';
- const all = await axios.get(base);
+ const all = await fetch(base).then(async (res) => Object.assign(res, { data: await res.json() })).catch(() => null);
console.log('\nGET /todos ->', all.status);
console.log(`Preview: ${all.data.todos.length} todos`);[POST 请求](https://nodejs.org/en/blog/migrations/axios-to-fetch#post-request)
code
const base = 'https://dummyjson.com/todos';
- const created = await axios.post(
- `${base}/add`, {
- todo: 'Use DummyJSON in the project',
- completed: false,
- userId: 5,
- }, {
- headers: { 'Content-Type': 'application/json' }
- }
- );
+ const created = await fetch(`${base}/add`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ todo: 'Use DummyJSON in the project',
+ completed: false,
+ userId: 5,
+ }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPOST /todos/add ->', created.status);
console.log('Preview:', created.data?.id ? `created id ${created.data.id}` : JSON.stringify(created.data).slice(0,200));[POST 表单请求](https://nodejs.org/en/blog/migrations/axios-to-fetch#post-form-request)
code
const formEndpoint = '/submit';
- const created = await axios.postForm(formEndpoint, {
- title: 'Form Demo',
- completed: false,
- });
+ const created = await fetch(formEndpoint, {
+ method: 'POST',
+ body: new URLSearchParams({
+ title: 'Form Demo',
+ completed: false,
+ }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('Preview:', created.data);[PUT 请求](https://nodejs.org/en/blog/migrations/axios-to-fetch#put-request)
code
const base = 'https://dummyjson.com/todos';
- const updatedPut = await axios.put(
- `${base}/1`,
- { completed: false },
- { headers: { 'Content-Type': 'application/json' } }
- );
+ const updatedPut = await fetch(`${base}/1`, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ completed: false }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPUT /todos/1 ->', updatedPut.status);
console.log('Preview:', updatedPut.data?.completed !== undefined ? `completed=${updatedPut.data.completed}` : JSON.stringify(updatedPut.data).slice(0,200));[DELETE 请求](https://nodejs.org/en/blog/migrations/axios-to-fetch#delete-request)
code
const base = 'https://dummyjson.com/todos';
- const deleted = await axios.delete(`${base}/1`);
+ const deleted = await fetch(`${base}/1`, { method: 'DELETE' })
+ .then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nDELETE /todos/1 ->', deleted.status);
console.log('Preview:', deleted.data ? JSON.stringify(deleted.data).slice(0,200) : typeof deleted.data);[`request` Axios 方法](https://nodejs.org/en/blog/migrations/axios-to-fetch#request-axios-method)
code
const base = 'https://dummyjson.com/todos';
diff
- const customRequest = await axios.request({
- url: `${base}/1`,
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- data: { completed: true },
- });
+ const customRequest = await fetch(`${base}/1`, {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ completed: true }),
+ }).then(async (res) => Object.assign(res, { data: await res.json() }));
console.log('\nPATCH /todos/1 ->', customRequest.status);
console.log('Preview:', customRequest.data?.completed !== undefined ? `completed=${customRequest.data.completed}` : JSON.stringify(customRequest.data).slice(0,200));[不受支持的 API](https://nodejs.org/en/blog/migrations/axios-to-fetch#unsupported-apis)
该代码转换工具目前尚未覆盖直接请求辅助函数之外的 Axios 功能,例如拦截器、取消令牌或通过 axios.create() 创建的实例配置。
[致谢](https://nodejs.org/en/blog/migrations/axios-to-fetch#recognition)
我们要感谢 Axios 的维护者们长期以来对该软件包的支持以及为生态系统做出的贡献。