Skip to content

node-fetch should provide a polyfill entrypoint #1317

Description

@tarikjn

This has been an issue that has came back to me several times, but the fact that v3 is ESM-only module makes this a pain point with node-fetch. Read more bellow:

When is this an issue?

  • using a library that expects fetch available as a global
  • working with an isomorphic codebase
  • you want to run a module/some code originally designed for the browser in your node codebase

Why are the existing solutions inappropriate?

The doc suggests doing this:

import fetch from 'node-fetch';

if (!globalThis.fetch) {
  globalThis.fetch = fetch;
}

But this is actually problematic with ESM modules. If you use a library expecting fetch as a global (eg. react-relay-network-modern). There are typically three locations where you would import node-fetch:

  1. right before you import the library (unless you also run that code in the browser)
  2. in your server entry point
  3. in your bundler entry point

In all three cases using ES imports the above code won't be guaranteed to have assigned fetch on the global object before something is done with it, and so the only way to address that is to use an import file specifically for polyfilling.

Solutions

The correct solution is to provide a polyfill entrypoint that can be used for this purpose:

import 'node-fetch/polyfill';

This can either be implemented on this project or with an external package. An external package would either include node-fetch as a peer dependency, requiring the user to use 2 packages, or worse, it may be using node-fetch as a dependency.

Either way, this is an issue that will keep coming back until a proper solution is documented. Perhaps a middle-ground solution is to link to a module that properly polyfill node-fetch in the documentation.

Prior art and discussion

#119 (by yours truly)
#521

Why does this belongs on this package?

  1. This is a polyfill for node, not for any other environment. I agree with @bitinn that providing a browser.js file was out of scope:

    On Polyfill self #537

    Thx for the PR but I believe this is better left for third-party module, where the author knows exactly what they want.

    (we made mistake providing a browser.js and we regret it since, as people use it differently and sometimes in non-nodejs environment like react-native.)

  2. There is pretty much only one way to do it, Adds polyfill support #119 and Provide global polyfills #521 both use the same approach.

Why is it an even bigger issue today than 5 years ago

  • node-fetch v3 being an ESM-only module, it will often require creating a separate file to properly polyfill it
  • browser code is now fairly safe to use fetch without any client polyfills and so it can be more frequently expected to rely on a global fetch

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions