Node.js `fetch` Compatibility Layer
node-fetch-native is a lightweight package designed to provide a consistent `fetch` API across various JavaScript runtimes, primarily targeting Node.js. It intelligently prefers Node.js's experimental native `fetch` (backed by `undici`) when available, falls back to an internal `node-fetch v3` implementation for older Node.js versions, and offers comprehensive HTTP/HTTPS proxy support, which is not natively available in Node.js's built-in `fetch` implementation. Currently stable at version `1.6.7`, the package maintains a steady release cadence, often addressing dependency updates and minor bug fixes. A key differentiator is its ability to bridge the `CommonJS` (`require`) and `ESM` (`import`) divide for `fetch`, resolving common migration issues encountered with `node-fetch` v3. It also provides a polyfill mechanism to ensure global `fetch` availability.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module ... node-fetch-native ... not supported.
cause Attempting to `require()` an ESM-only package like `node-fetch` v3, which this package wraps, in a strict CommonJS environment without proper resolution.fixUse `node-fetch-native` with `require('node-fetch-native')` as it provides a CommonJS-compatible export. If explicitly trying to load `node-fetch` directly, ensure your project is configured for ESM or use an older `node-fetch` v2. -
Warning: `node-fetch-native/node` is loaded in a non-Node.js environment. Consider importing from `node-fetch-native` directly if this is not intended.
cause This warning occurs when you explicitly import the Node.js-specific `node-fetch-native/node` subpath in a runtime that is detected as non-Node.js.fixIf you are running in a Node.js environment and want to disable this warning, set the `DISABLE_NODE_FETCH_NATIVE_WARN=1` environment variable. If you are not in Node.js, reconsider if you need the Node.js-specific implementation. -
Fetch requests are not routing through my HTTP proxy.
cause HTTP proxy support for `fetch` in Node.js (including native `fetch`) requires explicit configuration, typically via environment variables, as it's not a built-in feature.fixEnsure `HTTP_PROXY` and `HTTPS_PROXY` environment variables are correctly set before starting your application. For example, `export HTTP_PROXY=http://your.proxy.com:port`.
Warnings
- breaking The underlying `node-fetch` package moved to ESM-only in v3, breaking `require()` usage for many projects. While `node-fetch-native` provides compatibility for both CommonJS and ESM, users migrating from older `node-fetch` versions should be aware of this ecosystem shift.
- gotcha When importing from `node-fetch-native/node` to explicitly use the non-native implementation, a warning may be logged if the current runtime is not Node.js.
- gotcha HTTP/HTTPS proxy support relies on standard environment variables (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`). If these are not correctly configured, proxy functionality will not activate.
- gotcha The package attempts to prefer Node.js's native `fetch` when available. If you experience unexpected behavior or need specific `node-fetch` features not present in the native implementation, you might need to force the non-native version.
Install
-
npm install node-fetch-native -
yarn add node-fetch-native -
pnpm add node-fetch-native
Imports
- fetch
const fetch = require('node-fetch-native');import fetch from 'node-fetch-native';
- fetch (CommonJS)
import fetch from 'node-fetch-native';
const fetch = require('node-fetch-native'); - Named exports (Headers, Request, Response)
const { Headers, Request, Response } = require('node-fetch-native');import { fetch, Headers, Request, Response } from 'node-fetch-native'; - Force non-native fetch
import { fetch } from 'node-fetch-native/node';import fetch from 'node-fetch-native/node';
- Polyfill global fetch
require('node-fetch-native/polyfill');import 'node-fetch-native/polyfill';
Quickstart
import fetch, { Headers, Request } from 'node-fetch-native';
import 'node-fetch-native/polyfill'; // Optional: ensures global fetch is available
async function runExample() {
console.log("--- Basic Fetch Example ---");
try {
const response = await fetch("https://api.github.com/zen");
const text = await response.text();
console.log(`GitHub Zen says: "${text}"`);
} catch (error) {
console.error("Basic fetch failed:", error);
}
console.log("\n--- Fetch with Named Exports Example ---");
try {
const headers = new Headers({ "Content-Type": "application/json" });
const request = new Request("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: headers,
body: JSON.stringify({ title: "foo", body: "bar", userId: 1 }),
});
const response = await fetch(request);
const data = await response.json();
console.log("POST request response:", data);
} catch (error) {
console.error("Named exports fetch failed:", error);
n}
// Example of using a proxy (requires setting environment variables like HTTP_PROXY)
if (process.env.HTTP_PROXY || process.env.HTTPS_PROXY) {
console.log("\n--- Proxy-aware Fetch (if env vars are set) ---");
try {
const response = await fetch("http://example.com");
console.log(`Fetched http://example.com via proxy (status: ${response.status})`);
} catch (error) {
console.error("Proxy fetch failed:", error);
}
} else {
console.log("\n--- Proxy-aware Fetch: Set HTTP_PROXY or HTTPS_PROXY environment variable to test. ---");
console.log("Example: export HTTP_PROXY=http://localhost:8080");
}
}
runExample();