vercel/next.js

Cache handler ERR_MODULE_NOT_FOUND when using ESM modules

hdodov opened this issue · 1 comments

Link to the code that reproduces this issue

https://github.com/hdodov/test-nextjs/tree/cache-handler-not-working

To Reproduce

  1. Clone the repo https://github.com/hdodov/test-nextjs/tree/cache-handler-not-working
  2. npm i
  3. npm run dev
  4. You'll see the error

Current vs. Expected behavior

I have "type": "module" in my package.json, so I can't add the cache handler like this, as the docs suggest:

module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
}

Instead, I need to add it like this:

module.exports = {
- cacheHandler: require.resolve('./cache-handler.js'),
+ cacheHandler: import.meta.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
}

However, when I do so, I get the following error on npm run dev:

$ npm run dev

> test-nextjs@0.1.0 dev
> next dev

   ▲ Next.js 15.1.0
   - Local:        http://localhost:3000
   - Network:      http://192.168.100.16:3000

 ✓ Starting...
 ✓ Ready in 1625ms
[Error: Cannot find module '/Users/hristiyan.dodov/Projects/test-nextjs/.next/file:/Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js' imported from /Users/hristiyan.dodov/Projects/test-nextjs/node_modules/next/dist/server/next-server.js] {
  code: 'ERR_MODULE_NOT_FOUND',
  url: 'file:///Users/hristiyan.dodov/Projects/test-nextjs/.next/file:/Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js'
}

…and I also get it if I try npm run build directly:

$ npm run build

> test-nextjs@0.1.0 build
> next build

   ▲ Next.js 15.1.0

   Creating an optimized production build ...
 ✓ Compiled successfully
 ✓ Linting and checking validity of types    

> Build error occurred
[Error: Cannot find module '/Users/hristiyan.dodov/Projects/test-nextjs/file:/Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js' imported from /Users/hristiyan.dodov/Projects/test-nextjs/node_modules/next/dist/export/helpers/create-incremental-cache.js] {
  type: 'Error',
  code: 'ERR_MODULE_NOT_FOUND',
  url: 'file:///Users/hristiyan.dodov/Projects/test-nextjs/file:/Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js'
}

Check these two branches:

Here's a diff between the two: hdodov/test-nextjs@cache-handler-working...cache-handler-not-working

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 23.6.0: Thu Sep 12 23:34:49 PDT 2024; root:xnu-10063.141.1.701.1~1/RELEASE_X86_64
  Available memory (MB): 32768
  Available CPU cores: 16
Binaries:
  Node: 20.17.0
  npm: 10.8.2
  Yarn: N/A
  pnpm: 9.15.0
Relevant Packages:
  next: 15.1.0 // Latest available version is detected (15.1.0).
  eslint-config-next: 15.1.0
  react: 19.0.0
  react-dom: 19.0.0
  typescript: 5.7.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Module Resolution

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local)

Additional context

No response

I logged the difference between require.resolve and import.meta.resolve:

console.log(require.resolve("./cache-handler.js"));
// /Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js

console.log(import.meta.resolve("./cache-handler.js"));
// file:///Users/hristiyan.dodov/Projects/test-nextjs/cache-handler.js

It seems that file:// should be removed.

Also, the file should be cache-handler.cjs, rather than cache-handler.js. Otherwise you get this error:

ReferenceError: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/Users/hristiyan.dodov/Projects/test-nextjs/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at <unknown> (cache-handler.js:5:1)

Here's the fix: hdodov/test-nextjs@b0f3757

const nextConfig = {
  cacheHandler: import.meta.resolve("./cache-handler.cjs").replace("file://", ""),
  cacheMaxMemorySize: 0,
};

However, I think that Next.js should handle this more adequately or at least put it in the docs…