资讯动态

node-fetch v3 升级指南:从 v2 迁移到 Fetch 标准的破坏性变更与增强特性全解析

发布时间:2026/9/25 4:45:34 来源:尧图企业网站定制
后端【免费下载链接】node-fetchA light-weight module that brings the Fetch API to Node.js项目地址https://gitcode.com/gh_mirrors/no/node-fetch点击查看免费下载node-fetch v3.x 是向 WHATWG Fetch Standard 全面看齐的一次重大重构它提升最低 Node.js 版本、改为纯 ES Module 分发、移除timeout选项与非标准 API同时带来data:URI、暴露 Blob、更好的 UTF-8 URL 处理等新能力。本文以官方升级指南docs/v3-UPGRADE-GUIDE.md为主线结合本仓库的源码实现与测试用例逐条拆解每项破坏性变更的动机、影响范围与迁移方案帮助你快速完成从 v2 到 v3 的平滑过渡。升级总览v3.x 的改动方向非常明确尽可能贴合 Fetch Standard删掉一切非标准行为与私有 API。官方升级指南强调本文档并非全部变更的穷举清单而是最重要的破坏性变更集合其他相对次要的改动请查阅项目发布说明与 v2 升级指南其中记录的Headers规范化、.text()编码行为等改动在 v3 中继续延续。在动手升级前建议先对代码库做一次破坏性 API 扫描重点检查以下关键词timeout选项、textConverted()、require(node-fetch)new Request(相对路径)、new Response(相对路径)、res.body.on(error)res.json()的错误处理分支中对FetchError的判断一、运行环境与模块系统的变化1.1 最低 Node.js 版本提升至 12.20自 2020 年 5 月起 Node.js 10 已进入 EOL 周期v3 据此彻底放弃了对 Node.js 4、6、8、10 的支持这些版本在 v2 中仍可运行。当前仓库的 package.json 明确声明了引擎范围engines: { node: ^12.20.0 || ^14.13.1 || 16.0.0 }升级到 12.20 以上版本不仅是满足 node-fetch 的硬性要求也让 Node.js 原生提供AbortController14.17、完整 WHATWG URL API 等 v3 依赖的能力。如果你仍停留在旧版本应优先升级运行时本身否则 v3 无法安装或启动。1.2 ESM-only不再支持require()v3 从3.0.0-beta.10起被转换为纯 ES Module 包。仓库的 package.json 中type: module字段即是证据。这意味着// 以下写法在 v3 中会直接报错 const fetch require(node-fetch); // ERR_REQUIRE_ESM: Must use import to load ES Module迁移策略如果项目本身就是 ESM直接改用importimport fetch from node-fetch;如果项目仍基于 CommonJS官方给出两条出路继续使用 v2v2 基于 CommonJS 构建且官方承诺会继续为其发布关键 bug 修复。安装时锁定大版本即可npm install node-fetch2用异步import()从 CommonJS 加载 v3// mod.cjs const fetch (...args) import(node-fetch).then(({default: fetch}) fetch(...args));注意这种包装只解决了能否拿到 fetch 函数的问题Headers、Request、Response等类同样只能通过异步import()获取异步上下文会带来额外的调用成本与类型系统复杂度建议仅在无法整体迁移 ESM 时使用。1.3 从 CommonJS 迁移的配套检查ESM-only 还会连带影响你的测试框架、打包工具与类型配置TypeScript若项目使用module: commonjs即使装了 v3 也无法同步导入需将模块目标升级为node16/nodenext或esnext详见后文捆绑 TypeScript 类型一节。测试工具本仓库自身的测试如 test/main.js全部使用import语法迁移时需检查现有require(node-fetch)出现在哪些模块并逐一处理。二、请求控制与超时机制的变革2.1timeout选项被移除timeout从未属于 Fetch Standardv3 将其彻底删除。原因是规范化的AbortSignal能提供更细粒度的请求超时控制且已是 Fetch 规范的一部分。若你的代码写过fetch(url, {timeout: 5000})升级后该选项会被静默忽略——请求将不再按时限中断这是最隐蔽的线上隐患之一。2.2 用 AbortSignal 实现超时官方推荐借助第三方timeout-signal包快速迁移代码形态如下import timeoutSignal from timeout-signal; import fetch from node-fetch; const {AbortError} fetch; fetch(https://www.google.com, {signal: timeoutSignal(5000)}) .then(response { // 正常处理响应 }) .catch(error { if (error instanceof AbortError) { // 处理超时 } });也可以不引入任何依赖直接使用 Node.js 原生AbortControllerNode 14.17 全局可用手动实现来自 README.md 的官方示例import fetch, {AbortError} from node-fetch; const AbortController globalThis.AbortController || await import(abort-controller); const controller new AbortController(); const timeout setTimeout(() { controller.abort(); }, 150); try { const response await fetch(https://example.com, {signal: controller.signal}); const data await response.json(); } catch (error) { if (error instanceof AbortError) { console.log(request was aborted); } } finally { clearTimeout(timeout); }实现层面的印证从 src/index.js 可以看到 v3 对signal的完整处理链路——fetch内部监听abort事件触发abort()函数reject 一个AbortError定义于 src/errors/abort-error.js销毁请求体流并在响应体上emit(error, error)。若请求尚未完成abort监听还会被finalize()及时移除避免事件泄漏。在 src/request.js 中signal必须是AbortSignal或EventTarget实例否则抛出TypeError。2.3req.body不再接受字符串v3 正朝着body 要么为 null、要么为流的方向演进因此请求体不再是字符串。仓库 body.js 的构造函数展示了 v3 实际接受的 body 类型null、URLSearchParams、Blob、Buffer、ArrayBuffer、ArrayBufferView、Stream、FormData以及其他可被String()强转的值。迁移时请将字符串 body 改写为规范形态例如使用URLSearchParams或Buffer.from(str)// v2 时代的写法在 v3 中已不受推荐 await fetch(url, {method: POST, body: keyvalue}); // 推荐改用 URLSearchParamsContent-Type 自动设为 // application/x-www-form-urlencoded;charsetUTF-8 const params new URLSearchParams({key: value}); await fetch(url, {method: POST, body: params});对应地src/body.js 的extractContentType()会为URLSearchParams自动生成application/x-www-form-urlencoded;charsetUTF-8为字符串生成text/plain;charsetUTF-8。2.4 任意 URL 不再支持v3 全面改用 WHATWG 的new URL()解析输入src/request.js 中parsedURL new URL(input)因此缺少 base 的任意 URL 字符串将解析失败。例如// v2 中可运行的写法v3 会抛 TypeError: Invalid URL await fetch(//example.com/path); await fetch(/relative/path);这要求调用方始终提供完整、合法的绝对 URLhttp:、https:、data:详见下文相对 URL 创建 Request/Response 不再支持。三、Response 行为的变化3.1statusText不再自动派生默认值v2 时代如果服务端没有返回状态文本node-fetch 会根据 HTTP 状态码自动补一个默认消息如 404 → Not Found。这一行为不符合 Fetch Standardv3 中statusText保持空白字符串。仓库 src/response.js 中构造逻辑直接写为statusText: options.statusText || 不再有任何派生逻辑。测试 test/main.js 也专门验证了这一点it(should handle response with no status text, async () { const url ${base}no-status-text; const res await fetch(url); expect(res.statusText).to.equal(); // 期望为空字符串 await res.arrayBuffer(); });迁移影响任何依赖res.statusText OK或根据statusText判断语义的代码都需要改为依赖res.status或res.ok见 src/response.js 中ok的定义status 200 status 300。3.2res.textConverted()被移除textConverted()是 v2 为保留 v1 编码探测行为而提供的非标准方法v3 将其删除。需要字符集检测时官方推荐改用第三方fetch-charset-detection包import fetch from node-fetch; import convertBody from fetch-charset-detection; fetch(https://somewebsite.com).then(async res { const buf await res.arrayBuffer(); const text convertBody(buf, res.headers); });背后的行为变迁v2 起.text()已固定按 UTF-8 解码这是 Fetch Standard 的要求详见 docs/v2-UPGRADE-GUIDE.md 中 .text()no longer tries to detect encoding 一节v3 延续此行为——src/body.js 中text()使用new TextDecoder().decode(buffer)即始终 UTF-8。仓库还保留了 test/external-encoding.js 用于外部编码场景的测试但 v3 自身不再提供自动探测。3.3res.json()解析失败时抛出SyntaxErrorv3 中当res.json()遇到非法 JSON 时抛出的是SyntaxError而非 v2 的FetchError以对齐规范。这直接源于 src/body.js 的实现async json() { const text await this.text(); return JSON.parse(text); // JSON.parse 失败即抛 SyntaxError }测试 test/main.js 验证了对非法 JSON 的拒绝行为it(should reject invalid json response, async () { const url ${base}error/json; const res await fetch(url); expect(res.headers.get(content-type)).to.equal(application/json); return expect(res.json()).to.eventually.be.rejectedWith(Error); });迁移影响如果你的错误处理逻辑依赖error instanceof FetchError来捕获 JSON 解析失败必须增加对SyntaxError的判断分支同时注意区分HTTP 层错误FetchError与解析层错误SyntaxError两种语义。3.4 流错误转发与on(error)监听v3 使用 Node.js 的stream pipeline转发请求/响应错误详见后文增强部分。这对消费响应体的方式有一个直接影响错误可能被触发两次。在 Node.js ≥ 13.5 环境下如果你用res.body.on(error, () ...)监听错误回调可能被调用两次官方建议改为res.body.once(error, () ...)// v2 的写法 res.body.on(error, () handleBodyError()); // v3 的推荐写法 res.body.once(error, () handleBodyError());从 src/index.js 可以看到响应体body正是通过pump(response_, new PassThrough(), ...)pump即stream.pipeline的别名构建的pipeline 会把错误回调传递给PassThrough流因此同一错误存在多次传播的路径。四、包结构与导出的变化4.1browser字段被移除v2 的 package.json 中包含browser字段用于服务端/浏览器双端场景v3 明确 node-fetch只面向服务端移除了该字段。若你在浏览器端使用 node-fetch官方建议切换为cross-fetch这类浏览器兼容实现而不是继续依赖 node-fetch 的浏览器入口。4.2 默认 User-Agent 变更默认 User-Agent 从node-fetch/1.0 (https://github.com/node-fetch/node-fetch)改为node-fetch (https://github.com/node-fetch/node-fetch)这个字符串不再带版本号。若你的服务端依赖 User-Agent 做版本识别或限流白名单需要同步更新匹配规则。实现位于 src/request.jsif (!headers.has(User-Agent)) { headers.set(User-Agent, node-fetch); }注意仅在请求方未显式传入User-Agent头时才使用该默认值因此你可以通过headers选项覆盖它。4.3 捆绑 TypeScript 类型v3 起不再需要安装types/node-fetch类型定义直接随包分发。package.json 中types: ./types/index.d.ts指向仓库内置的 types/index.d.ts。该声明文件完整覆盖fetch()主函数签名fetch(url: URL | RequestInfo, init?: RequestInit): PromiseResponseHeaders、Request、Response、FetchError、AbortError等类RequestInit中 node-fetch 特有的扩展选项agent、compress、follow、counter、size、highWaterMark、insecureHTTPParser等从fetch-blob重新导出的Blob、File、blobFrom、fileFrom等类型类型正确性还由 types/index.test-d.ts 配合tsd测试保障npm run test-types。迁移时请卸载types/node-fetch避免两套类型定义冲突。五、v3 带来的能力增强5.1data:URI 支持v2 只支持http:协议Fetch Standard 引入data:URI 后v3 按规范实现了它。源码入口在 src/index.js 与 src/index.jsconst supportedSchemas new Set([data:, http:, https:]); // ... if (parsedURL.protocol data:) { const data dataUriToBuffer(request.url); const response new Response(data, {headers: {Content-Type: data.typeFull}}); resolve(response); return; }即data:URI 会通过data-uri-to-buffer解码为 Buffer并自动带上解析出的 Content-Type。test/external-encoding.js 提供了丰富用例覆盖 base64 图片、指定 charset、纯文本以及非法 data URI 的拒绝// base64 编码的 GIF const b64 data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs; const res await fetch(b64); // res.headers.get(Content-Type) image/gif // 纯文本 data URI await fetch(data:,Hello%20World!); // Content-Type 为 text/plain;charsetUS-ASCIItext() 返回 Hello World!5.2 新暴露的 Blob 实现v2 中Blob类型只在内部使用、不对外导出v3 起 Blob 实现迁移到fetch-blob包并成为公开 API。src/index.js 从fetch-blob/from.js导入并同时导出export {FormData, Headers, Request, Response, FetchError, AbortError, isRedirect}; export {Blob, File, fileFromSync, fileFrom, blobFromSync, blobFrom};这意味着你可以直接构造 Blob 作为请求体或读取响应为 Blobimport fetch, {Blob} from node-fetch; // 以 Blob 作为请求体 await fetch(url, {method: POST, body: new Blob([a1])}); // 读取响应为 Blob const blob await (await fetch(url)).blob(); const text await blob.text();测试 test/main.js 验证了 Blob 的text()、arrayBuffer()、stream()读取以及fetch → blob → 回传的往返流程。5.3 更好的 UTF-8 URL 处理v3 使用 Node.js 内置的WHATWG-compliant URL API解析 URLsrc/request.js 中parsedURL new URL(input)因此非 ASCII 的 UTF-8 URL 能被正确处理和编码不再出现 v2 时代的乱码问题。5.4 使用stream.pipeline转发错误由于 v3 最低要求 Node.js 12.20可以放心使用stream.pipeline这一新版 API。请求错误如 DNS 失败、连接被拒经由 pipeline 转发到响应体流调用方能在res.body上收到统一的错误事件。仓库中的使用点包括 src/index.js构建响应体以及 src/index.jsgzip 解压管道。这也是前文错误可能触发两次警告的根源务必用once(error)消费。5.5 相对 URL 创建 Request/Response 不再支持与任意 URL 不再支持同源v3 引入new URL()后由于 Node.js 缺乏浏览器那样的 browsing context且当时的 WHATWG URL API 存在限制无法在无 base 的情况下解析相对 URL因此new Request(/path)、new Response(/path)会直接抛错。fetch()主函数只接受绝对 URL 与data:URL。迁移时要特别留意以相对路径拼接请求的代码统一改为// 先解析为绝对 URL const url new URL(/api/data, https://example.com).toString(); await fetch(url);六、升级自查清单将上述变更浓缩为一份可执行的迁移检查表供升级过程中逐项核对变更项v2 行为v3 行为迁移动作Node.js 版本支持 4/6/8/10最低 12.20package.json升级运行时模块格式CommonJSESM-onlypackage.json改用import或异步import()必要时锁定node-fetch2timeout选项可用移除改用AbortSignaltimeout-signal或原生AbortControllerreq.body字符串可用不再接受改用URLSearchParams/Buffer/Blob/流statusText自动派生默认值保持空白字符串src/response.js改用res.status/res.ok判断res.textConverted()存在移除用fetch-charset-detection手动转换res.json()错误FetchErrorSyntaxErrorsrc/body.js错误处理增加SyntaxError分支res.body.on(error)单次触发可能触发两次改用once(error)browser字段存在移除浏览器场景切换cross-fetch默认 User-Agent带版本号node-fetch (...)src/request.js更新 UA 匹配规则types/node-fetch需额外安装类型随包内置types/index.d.ts卸载外部类型包data:URI不支持支持src/index.js可直接使用Blob内部类型公开导出src/index.js可直接导入相对 URL可用抛错src/request.js统一转为绝对 URL最后两点建议升级时先在测试环境完整跑一遍本仓库通过npm test运行 mocha 测试套件重点回归超时、编码与错误处理路径若团队尚未准备好迁移 ESM官方明确承诺 v2 会持续获得关键 bug 修复可以在锁定node-fetch2的同时规划渐进式迁移。赞分享后端【免费下载链接】node-fetchA light-weight module that brings the Fetch API to Node.js项目地址https://gitcode.com/gh_mirrors/no/node-fetch点击查看免费下载相关推荐openai-node 迁移指南全面解析从 node-fetch 到内置 Web fetch 的破坏性变更openai node 迁移指南全面解析从 node fetch 到内置 Web fetch 的破坏性变更 本文基于 MIGRATION.md https:/AI 应用大模型后端React Query v3 迁移指南从 v2 升级的破坏性变更与新增能力全解析React Query v3 迁移指南从 v2 升级的破坏性变更与新增能力全解析 React Query 在 v2 时代引入了大量新特性与魔法也因此积累前端缓存状态管理Node-fetch v2到v3迁移终极指南避坑技巧与新特性全解析Node fetch v2到v3迁移终极指南避坑技巧与新特性全解析 如果你正在使用Node.js进行网络请求那么node fetch这个轻量级模块很可后端上一篇告别任务栏闪烁TranslucentTB与Explorer.exe的和谐共存之道下一篇Hugo Blog Awesome社交图标集成支持300平台的完整列表和配置指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑