isomorphic-fetch vs cross-fetch vs node-fetch
Node.js 与浏览器环境下的 Fetch 实现方案对比
isomorphic-fetchcross-fetchnode-fetch类似的npm包:

Node.js 与浏览器环境下的 Fetch 实现方案对比

cross-fetch、isomorphic-fetch 和 node-fetch 都是为了解决 JavaScript 在不同运行时(Node.js 与浏览器)中 fetch API 不一致的问题。node-fetch 专为 Node.js 环境设计,提供了轻量级的 HTTP 请求能力;isomorphic-fetch 和 cross-fetch 则是 polyfill 方案,旨在让同一套代码能在服务端和客户端无缝运行。随着 Node.js 18+ 原生支持 fetch,以及模块系统(ESM vs CJS)的演变,这三个包在架构选型中的定位发生了显著变化。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
isomorphic-fetch6,455,6996,902-576 年前MIT
cross-fetch01,69493.3 kB272 年前MIT
node-fetch08,847107 kB2493 年前MIT

cross-fetch vs isomorphic-fetch vs node-fetch: 架构选型与运行时兼容性深度解析

在构建全栈 JavaScript 应用时,HTTP 请求是不可或缺的一环。虽然浏览器原生支持 fetch API,但 Node.js 环境(尤其是 18 版本之前)长期缺乏标准实现。cross-fetch、isomorphic-fetch 和 node-fetch 都曾是为了解决这一鸿沟而诞生的方案,但它们的设计目标和适用场景截然不同。让我们从架构师的角度,深入对比它们在环境兼容性、模块系统和支持周期上的差异。

🌍 环境兼容性:专用 vs 通用

node-fetch 是专为 Node.js 环境设计的轻量级实现。

  • 它不包含浏览器 polyfill 代码,体积更小。
  • 仅能在 Node.js 中运行,直接引入浏览器会报错。
// node-fetch: 仅服务端使用
import fetch from 'node-fetch'; // v3 ESM
// const fetch = require('node-fetch'); // v2 CJS

const res = await fetch('https://api.example.com/data');

isomorphic-fetch 旨在抹平环境差异,自动检测运行时。

  • 在 Node 中引入 node-fetch,在浏览器中引入原生 fetch。
  • 但它是通过副作用(side-effect)全局注入,可能污染全局作用域。
// isomorphic-fetch: 全局注入
import 'isomorphic-fetch'; 
// 之后即可直接使用全局 fetch
const res = await fetch('https://api.example.com/data');

cross-fetch 同样追求通用性,但提供了更灵活的导入方式。

  • 允许作为默认导出导入,不强制污染全局。
  • 支持 Node.js、浏览器甚至 React Native,兼容性最广。
// cross-fetch: 显式导入
import fetch from 'cross-fetch';

const res = await fetch('https://api.example.com/data');

📦 模块系统陷阱:ESM vs CommonJS

这是当前选型中最容易踩坑的地方,尤其是 node-fetch 的版本迭代。

node-fetch 在 v3 版本做出了破坏性更新。

  • v3 版本仅支持 ESM(import),不能在 CommonJS(require)中直接使用。
  • 这导致许多旧项目无法升级,或需要复杂的配置 workaround。
// node-fetch v3: 必须使用 ESM
import fetch from 'node-fetch';

// node-fetch v2: 支持 CommonJS
const fetch = require('node-fetch');

isomorphic-fetch 主要基于 node-fetch v2 构建。

  • 天然支持 CommonJS,但在现代 ESM 项目中可能显得过时。
  • 缺乏对最新 Node.js 特性的适配。
// isomorphic-fetch: 传统方式
import 'isomorphic-fetch'; // 副作用导入

cross-fetch 对模块系统的支持最为平滑。

  • 同时提供 ESM 和 CommonJS 构建版本。
  • 在 TypeScript 项目中类型定义支持更好,减少配置麻烦。
// cross-fetch: 兼容两种模式
import fetch from 'cross-fetch'; // ESM
// const fetch = require('cross-fetch'); // CJS

🛑 维护状态与原生替代方案

随着 Node.js 18 正式发布,全局 fetch 已成为标准,这改变了选型逻辑。

isomorphic-fetch 目前已处于非活跃维护状态。

  • 社区普遍建议不再在新项目中使用。
  • 如果现在强行使用,可能会在未来 Node.js 版本升级时遇到冲突。
// ⚠️ 不推荐:isomorphic-fetch
// 维护频率低,依赖陈旧
import 'isomorphic-fetch';

node-fetch 仍在维护,但定位发生变化。

  • 对于 Node.js 18+ 项目,官方建议直接使用原生 fetch。
  • 仅在需要兼容旧版 Node 或需要特定扩展功能时才考虑。
// ✅ 推荐:Node 18+ 原生 fetch
const res = await fetch('https://api.example.com/data');

// ⚠️ 仅旧版 Node 需要:node-fetch
import fetch from 'node-fetch';

cross-fetch 保持活跃维护,定位清晰。

  • 专注于作为 polyfill 服务于尚不支持原生 fetch 的环境。
  • 适合需要发布 npm 包给他人使用的库作者。
// ✅ 推荐:跨平台库开发
import fetch from 'cross-fetch';
// 确保你的库在任何环境下都能工作

🤝 相似之处:共同的基石

尽管存在差异,这三个包在核心 API 上保持高度一致,都遵循 WHATWG Fetch 标准。

1. 📡 基本请求方式一致

  • 都支持 GET, POST, PUT, DELETE 等标准动词。
  • 请求体和响应体的处理方式(JSON, Text, Blob)相同。
// 所有包都支持的标准用法
const response = await fetch('/api', {
  method: 'POST',
  body: JSON.stringify({ data: 123 })
});
const json = await response.json();

2. 🔒 支持 AbortController

  • 都支持使用 AbortController 取消请求。
  • 这对于处理超时或组件卸载时的请求清理至关重要。
// 所有包都支持的取消请求
const controller = new AbortController();
const signal = controller.signal;

fetch('/api', { signal });
// 稍后调用 controller.abort() 取消

3. 🍪 Cookie 与 Header 处理

  • 都允许自定义请求头。
  • 在 Node 环境中都需要注意 Cookie 的手动管理(浏览器自动处理)。
// 所有包都支持的 Header 设置
fetch('/api', {
  headers: {
    'Authorization': 'Bearer token',
    'Content-Type': 'application/json'
  }
});

📊 总结:关键差异对比

特性node-fetchisomorphic-fetchcross-fetch
主要环境Node.js 专用Node + 浏览器 (Polyfill)Node + 浏览器 + React Native
模块系统v3 仅 ESM, v2 仅 CJS主要 CJSESM + CJS 双支持
维护状态活跃 (但建议用原生)❌ 非活跃/遗留✅ 活跃维护
全局污染否 (需导入)是 (副作用导入)否 (可显式导入)
Node 18+建议用原生 fetch不建议使用可作为 Polyfill 备用

💡 架构师建议

node-fetch 适合纯 Node.js 后端服务,但请务必检查你的 Node 版本。如果是 Node 18 或更高,请直接使用全局 fetch,无需安装任何包。如果是旧版 Node 且无法升级,v2 版本是稳定选择,v3 版本仅适用于 ESM 项目。

cross-fetch 是构建通用 npm 库的首选。如果你正在开发一个需要同时运行在服务端渲染(SSR)、客户端静态站点(SSG)甚至 React Native 中的库,它能最大程度减少环境适配代码。

isomorphic-fetch 应被视为遗留技术。除非你正在维护一个深度依赖它的旧项目,否则不要在新代码中引入。它的维护停滞意味着未来的安全风险和兼容性问题。

最终思考:JavaScript 运行时正在趋同。随着 Node.js 原生支持 fetch,polyfill 的需求正在减少。未来的架构趋势是:优先使用原生 API,仅在必须兼容旧环境时使用 cross-fetch 作为降级方案。

如何选择: isomorphic-fetch vs cross-fetch vs node-fetch

  • isomorphic-fetch:

    仅建议在维护旧有遗留代码时使用 isomorphic-fetch,新项目应避免引入。该包目前已处于非活跃维护状态,内部依赖较旧的 node-fetch 版本,在现代 ESM 项目或 Node.js 18+ 环境中可能会遇到兼容性问题或冗余 polyfill。

  • cross-fetch:

    如果你的项目需要构建通用库(Universal Library),或者需要在 Node.js、浏览器和 React Native 之间共享代码,请选择 cross-fetch。它 actively 维护,能自动处理不同环境的差异,且同时支持 ESM 和 CommonJS 模块系统,减少了配置负担。

  • node-fetch:

    如果你的代码仅运行在 Node.js 服务端,且版本低于 18(无原生 fetch),请选择 node-fetch。注意 v3 版本仅支持 ESM,若项目使用 CommonJS 则需锁定 v2 版本;若已是 Node.js 18+,则建议直接使用原生全局 fetch 而非此包。

isomorphic-fetch的README

isomorphic-fetch Build Status

Fetch for node and Browserify. Built on top of GitHub's WHATWG Fetch polyfill.

Warnings

  • This adds fetch as a global so that its API is consistent between client and server.

For ease-of-maintenance and backward-compatibility reasons, this library will always be a polyfill. As a "safe" alternative, which does not modify the global, consider fetch-ponyfill.

Why Use Isomorphic Fetch

The Fetch API is currently not implemented consistently across browsers. This module will enable you to use fetch in your Node code in a cross-browser compliant fashion. The Fetch API is part of the Web platform API defined by the standards bodies WHATWG and W3C.

Installation

NPM

npm install --save isomorphic-fetch

Bower

bower install --save isomorphic-fetch

Usage

require('isomorphic-fetch');

fetch('//offline-news-api.herokuapp.com/stories')
	.then(function(response) {
		if (response.status >= 400) {
			throw new Error("Bad response from server");
		}
		return response.json();
	})
	.then(function(stories) {
		console.log(stories);
	});

License

All open source code released by FT Labs is licenced under the MIT licence. Based on the fine work by jxck.

Alternatives