Skip to content

Instead change the require of index.js, to a dynamic import() which is available in all CommonJS modules ​

Problem Statement ​

When working with Node.js, you may encounter the error:

javascript
error [ERR_REQUIRE_ESM]: require() of ES Module [...] is not supported. Instead change the require of index.js to a dynamic import() which is available in all CommonJS modules

This error occurs when you try to use require() to import an ES Module (ECMAScript Module) package in a CommonJS environment. Many modern npm packages have transitioned to ESM-only distribution, which breaks compatibility with the traditional require() syntax.

WARNING

The problem typically occurs with packages like node-fetch, chalk, and others that have migrated to ES Modules in their newer versions while your code remains in CommonJS format.

Solutions ​

The most straightforward solution is to replace require() with dynamic import(), which works in both CommonJS and ESM environments:

javascript
// Replace this:
const fetch = require('node-fetch');

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

For multiple imports, use async/await syntax:

javascript
async function main() {
  const { default: FormData } = await import('form-data');
  const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
  const { default: chalk } = await import('chalk');
  
  // Your code here
}

main().catch(console.error);

2. Convert to ES Modules ​

If you can modify your project structure, convert it to use ES Modules:

  1. Add to package.json:
json
{
  "type": "module"
}
  1. Change require to import:
javascript
// Replace:
const path = require("path");
const fs = require("fs");

// With:
import path from "path";
import fs from "fs";
  1. Use .mjs extension for your files, or keep .js with "type": "module" in package.json

3. Downgrade Package Version (Temporary Fix) ​

If you need a quick fix, downgrade to a CommonJS-compatible version:

bash
npm uninstall node-fetch
npm install node-fetch@2.6.1

DANGER

This approach is not recommended long-term as you'll miss security updates and new features. Use it only as a temporary solution.

4. Alternative Packages ​

Consider using alternative packages that support CommonJS:

bash
npm install node-fetch-native

This package provides a polyfilled version that works with both module systems.

Complete Example with Dynamic Import ​

Here's how to rewrite the original code using dynamic imports:

javascript
async function processFiles() {
  // Dynamic imports
  const FormData = (await import('form-data')).default;
  const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
  const path = await import('path');
  const fs = await import('fs');
  
  const basePath = process.cwd();
  
  const files = fs.readdirSync(`${basePath}/build/images`);
  
  for (const file of files) {
    try {
      const formData = new FormData();
      const fileStream = fs.createReadStream(`${basePath}/build/images/${file}`);
      formData.append('file', fileStream);

      const url = 'https://api.nftport.xyz/v0/files';
      const options = {
        method: 'POST',
        headers: {
          Authorization: '[...]',
        },
        body: formData
      };
      
      const response = await fetch(url, options);
      const json = await response.json();
      const fileName = path.parse(json.file_name).name;
      const rawdata = fs.readFileSync(`${basePath}/build/json/${fileName}.json`);
      const metaData = JSON.parse(rawdata);

      metaData.file_url = json.ipfs_url;

      fs.writeFileSync(`${basePath}/build/json/${fileName}.json`, JSON.stringify(metaData, null, 2));

      console.log(`${json.file_name} uploaded & ${fileName}.json updated!`);
    } catch (err) {
      console.error('Error processing file:', file, err);
    }
  }
}

processFiles().catch(console.error);

Additional Considerations ​

  • Node.js Version: Ensure you're using a recent Node.js version (v14.8.0+ for top-level await support)
  • TypeScript Configuration: If using TypeScript, ensure your tsconfig.json is configured appropriately:
json
{
  "compilerOptions": {
    "module": "commonjs" // or "ESNext" if converting to ESM
  }
}
  • Error Handling: Always wrap dynamic imports in try/catch blocks for proper error handling

Conclusion ​

The ERR_REQUIRE_ESM error occurs when mixing CommonJS and ES Module systems. The recommended solution is to use dynamic imports (import()) which work in both environments. For long-term projects, consider migrating to ES Modules by adding "type": "module" to your package.json and converting all require() statements to import syntax.