Getting "must use import to load ES module" when using `node-fetch` in Netlify Functions

My site is skyglass.netlify.app.

I have a function that works locally with netlify dev. It requires node-fetch like this:

const fetch = require('node-fetch');

When I deploy however, I get this error:

{"errorType":"Error","errorMessage":"Must use import to load ES Module: /var/task/node_modules/node-fetch/src/index.js\nrequire() of ES modules is not supported.\nrequire() of /var/task/node_modules/node-fetch/src/index.js from /var/task/functions/subscribe.js is an ES module file as it is a .js file whose nearest parent package.json contains \"type\": \"module\" which defines all .js files in that package scope as ES modules.\nInstead rename index.js to end in .cjs, change the requiring code to use import(), or remove \"type\": \"module\" from /var/task/node_modules/node-fetch/package.json.\n","trace":["Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /var/task/node_modules/node-fetch/src/index.js","require() of ES modules is not supported.","require() of /var/task/node_modules/node-fetch/src/index.js from /var/task/functions/subscribe.js is an ES module file as it is a .js file whose nearest parent package.json contains \"type\": \"module\" which defines all .js files in that package scope as ES modules.","Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove \"type\": \"module\" from /var/task/node_modules/node-fetch/package.json.","","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1015:13)","    at Module.load (internal/modules/cjs/loader.js:863:32)","    at Function.Module._load (internal/modules/cjs/loader.js:708:14)","    at Module.require (internal/modules/cjs/loader.js:887:19)","    at require (internal/modules/cjs/helpers.js:74:18)","    at Object.<anonymous> (/var/task/functions/subscribe.js:3:15)","    at Module._compile (internal/modules/cjs/loader.js:999:30)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)","    at Module.load (internal/modules/cjs/loader.js:863:32)","    at Function.Module._load (internal/modules/cjs/loader.js:708:14)"]}

I tried changing the import to import fetch from 'node-fetch';, but then I got this error both locally and deployed:

{"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Cannot use import statement outside a module","trace":["Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module","    at _loadUserApp (/var/runtime/UserFunction.js:98:13)","    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)","    at Object.<anonymous> (/var/runtime/index.js:43:30)","    at Module._compile (internal/modules/cjs/loader.js:999:30)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)","    at Module.load (internal/modules/cjs/loader.js:863:32)","    at Function.Module._load (internal/modules/cjs/loader.js:708:14)","    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)","    at internal/main/run_main_module.js:17:47"]}

Hi @spacecrafter3d

I came across this a few days ago testing something locally. As per Loading and configuring the module

node-fetch from v3 is an ESM-only module - you are not able to import it with require() .

So you would now change

const fetch = require('node-fetch');

to

import fetch from 'node-fetch';

In doing so, you would need to change the node_bundler environment variable to esbuild e.g. in a netlify.toml file

[functions]
  node_bundler = "esbuild"

In order to use

const fetch = require('node-fetch');

you need to use node-fetch@2 (see npm docs) or load v3 asynchronously (from npm docs)

const fetch = (...args) => import('node-fetch')
              .then(({default: fetch}) => fetch(...args));
5 Likes

That did it, thanks!

EDIT: I believe I was on an older version of netlify-cli. An updated to that dep locally and everything was working again.


I was running across this problem for a function which only has one dependency (node-fetch)

I did exactly as you prescribed:

Changed const fetch = require("node-fetch") to import fetch from "node-fetch" as well as adding the node_bundler = "esbuild" config.

But now I’m getting an error pertaining to the node: prefix for core modules that’s being used inside the node-fetch package:

◈ Function builder zip-it-and-ship-it detected.
◈ Building functions from directory netlify/functions
 > node_modules/node-fetch/src/index.js:9:17: error: Could not resolve "node:http" (mark it as external to exclude it from the bundle)
    9 │ import http from 'node:http';
      ╵                  ~~~~~~~~~~~

 > node_modules/node-fetch/src/index.js:10:18: error: Could not resolve "node:https" (mark it as external to exclude it from the bundle)
    10 │ import https from 'node:https';
       ╵                   ~~~~~~~~~~~~

 > node_modules/node-fetch/src/index.js:11:17: error: Could not resolve "node:zlib" (mark it as external to exclude it from the bundle)
    11 │ import zlib from 'node:zlib';
       ╵                  ~~~~~~~~~~~

 > node_modules/node-fetch/src/index.js:12:52: error: Could not resolve "node:stream" (mark it as external to exclude it from the bundle)
    12 │ import Stream, {PassThrough, pipeline as pump} from 'node:stream';

Nobody else having that problem?

I’m on node v17 and have environment = { NODE_VERSION = "17" } set in my netlify.toml file

Hi @jimniels,

I’m not sure you’ll find a fix but I’ve been using the notes by @coelmay to setup a Function lately.

See the notes about node-fetch and node-fetch@2:

Hi @jimniels

Glad you have solved the issue.

There is an open issue whereby Netlify Dev Server (netlify dev) does not start in some instances when running on v17. If you run into this issue, downgrading to v16 (which is the current LTS version) is the only option (I believe)

Great work @Roneo.org. Very detailed write-up.