Does serverless function supports require-ESM on Node 22?

Does serverless function supports require-ESM on Node 22? In this blog post, it mentions “added support for require()ing synchronous ESM module graphs”. However, it doesn’t work in my deployment.

Current behavior

When I require an ESM-only library, e.g. uuid, Node throws ERR_REQUIRE_ESM.

Expected behavior

Node doesn’t throw when requiring an ESM-only library.

Code

Repository: GitHub - alvinleung1996/vercel-node22-require-esm-test: An Express.js application that uses the require-ESM feature

Steps to reproduce

  1. Install Node 22.18.0.
  2. Run yarn install.
  3. Run vercel dev.
  4. Open http://localhost:3000
  5. “require(‘uuid’) error” should be “null”.
  6. Run vercel deploy.
  7. “require(‘uuid’) error” is “Error [ERR_REQUIRE_ESM]…”.

Project information

Deployment: https://vercel-node22-require-esm-test.vercel.app
Node.js Version: 22.x

Hi @alvin-leung-concept4, I’m unable to recreate the local behaviour without using the --experimental-require-module flag.

This functionality was initially introduced in Node.js versions 22.0.0 and 20.17.0 behind the --experimental-require-module flag. In later versions, specifically Node.js v23.0.0, the feature was no longer behind this flag, and in v23.5.0, the experimental warning associated with it was removed by default.

I’m digging more to find a solution for you. Will share here when I have a working example.

Hi @alvin-leung-concept4, I was able to run your code on Vercel Nodejs v22 by providing the flag in the NODE_OPTIONS environment variable using vercel.json:

{
  "env": {
    "NODE_OPTIONS": "--experimental-require-module"
  },
  "rewrites": [{ "source": "/(.*)", "destination": "/api" }]
}

I hope this solves your issue.

Thank you for your response.

I couldn’t replicate your success. I have used your vercel.json, and it still doesn’t work.

I see the flag --no-experimental-require-module in process.execArgv and it overrides the --experimental-require-module flag in NODE_OPTIONS. Not sure how your deployment has the opposite flag set.

Here is my result:

Oh, I see. I deployed using Vercel CLI. Did you deploy using Vercel CLI or the GitHub integration?

By the way, I had changed the project structure a little bit:

I have try deploying using both GitHub integration and Vercel CLI, and the deployments always have the flag --no-experimental-require-module set in process.execArgv.