Can't import `node-fetch` in a Function in any way

Hello,
I have a simple Function in my website determined-hoover-41f81b that used to work flawlessly (it sends an online contact form to me as email via Sendinblue). At the moment I’m stuck with an error on line 1 with node-fetch, which I seem unable to import in any way.

I’ve read that with node-fetch v3.x it’s not possible anymore to:

const fetch = require('fetch');

In fact this triggers the error:

Error: require() of ES Module /Users/davidebarranca/Documents/Sites/CCExtensions/node_modules/node-fetch/src/index.js from /Users/davidebarranca/Documents/Sites/CCExtensions/functions/send-contact-form/send-contact-form.js not supported.
Instead change the require of index.js in /Users/davidebarranca/Documents/Sites/CCExtensions/functions/send-contact-form/send-contact-form.js to a dynamic import() which is available in all CommonJS modules.

I’ve read in this forum here that the recommended way is to:

import fetch from "node-fetch";

… and set node_bundler = "esbuild" in the netlify.toml. Which I did, resulting in the error:

SyntaxError: Cannot use import statement outside a module

I’ve then resolved to use the suggestion from the first error message (dynamic import) and I’ve grabbed the snippet from the node-fetch documentation page, so I’m now trying:

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

This result in a joke of an error:

SyntaxError: Unexpected token o in JSON at position 1
 JSON.parse (<anonymous>)
 Object.exports.handler (/Users/davidebarranca/Documents/Sites/CCExtensions/functions/send-contact-form/send-contact-form.js:11:35)
 Object._executeSync (/usr/local/lib/node_modules/netlify-cli/node_modules/lambda-local/build/lambdalocal.js:286:47)
 /usr/local/lib/node_modules/netlify-cli/node_modules/lambda-local/build/lambdalocal.js:95:26
 new Promise (<anonymous>)
 Object.execute (/usr/local/lib/node_modules/netlify-cli/node_modules/lambda-local/build/lambdalocal.js:87:16)
 Object.invokeFunction (/usr/local/lib/node_modules/netlify-cli/src/lib/functions/runtimes/js/index.js:58:36)
 NetlifyFunction.invoke (/usr/local/lib/node_modules/netlify-cli/src/lib/functions/netlify-function.js:123:41)
 processTicksAndRejections (node:internal/process/task_queues:96:5)
 async handler (/usr/local/lib/node_modules/netlify-cli/src/lib/functions/server.js:154:33)

I’m hence unable to fetch anything (I’ve discovered it the hard way, i.e. people complaining on forums that my contact form doesn’t work). What am I doing wrong here?
Thank you very much!

Davide

This, along with the node_bundler setting should work.

Could you share the entire function code or a minimal reproduction?

Sure, here it is in its entire glory :slight_smile:
Although it crashes directly at the fetch import, if I remove that line and substitute a hello-world-ish content, then it’s flawless :man_shrugging:t2:

// const fetch = require("node-fetch"); // nope
// const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // nope

import  fetch  from "node-fetch"; // nope

exports.handler = async (event, context) => {

  // stuff that comes from the FORM
  const { email, message } = JSON.parse(event.body);

  const apikey = process.env.SIB_API_KEY;
  const url = "https://api.sendinblue.com/v3/smtp/email";

  const options = {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      "api-key": apikey,
    },
    body: JSON.stringify({
      sender: { email: `${email}` },
      to: [{ name: "My Name", email: "myemail@something.com" }],
      replyTo: { email: `${email}` },
      htmlContent: `<html><body><h2>Contact form</h2><p>${message}</p></body></html>`,
      textContent: message,
      subject: "CC Extensions Contact Form",
    }),
  };

  let status;

  const result = await fetch(url, options)
    .then(res => {
      console.log("status?", res.status);
      status = res.status;
      return res.json();
    })
    .then(res => {
      console.log(res);
      return res;
    })
    .catch(err => {
      console.error(`Something went majestically wrong: ${err}`);
      return {
        statusCode: 500,
        body: JSON.stringify(err),
      };
    });

  return {
    statusCode: status,
    body: JSON.stringify(result),
  };
};

Could you try changing this to export async function handler(event, context) {}?

If that doesn’t change it, I’ll have to take another look, but that’s a start.

I’m afraid it doesn’t :frowning:

I’m not seeing the error with this setup:

https://github.com/Hrishikesh-K/musical-robot/tree/main

There must be something wrong elsewhere then in the repo, because I’m afraid I still get this:

Any idea where to look? It’s hosted on determined-hoover-41f81b. Thanks!

UPDATE: wait, let me check…

The error is unexpected token in JSON, which is happening because of your empty body, but in your code, you’re trying: const {foo, bar} = JSON.parse(event.body).

You’re right, the error I got now is due to the malformed body I’m (not) sending in the test POST.
Now node-fetch works!
I’m not entirely sure why—and what was wrong earlier—but I’m so glad it does. Thank you very much for the support! :pray:t2: