ES Modules in Node.js: package.json type field
When working with Node.js projects, you may encounter the error: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module. This typically occurs when your project configuration conflicts with JavaScript module systems. Here's what you need to know about the "type": "module" field in package.json and how to resolve these issues.
Understanding the package.json "type" field
The "type" field in package.json determines how Node.js interprets .js files in your project:
- Default behavior: Without a
"type"field or with"type": "commonjs", Node.js treats.jsfiles as CommonJS modules (usingrequire()andmodule.exports) - ES Module mode: With
"type": "module", Node.js treats.jsfiles as ES modules (usingimportandexportsyntax)
{
"name": "your-project",
"type": "module",
"scripts": {
"start": "node index.js"
}
}The Problem: Module System Conflicts
The error message you encountered indicates a mismatch between your module systems:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
require() of ES modules is not supported.This happens when:
- Your package.json has
"type": "module" - Your code uses
require()instead ofimport - You're trying to import an ES module file using CommonJS syntax
Solutions
Solution 1: Consistent Module Usage
Ensure your code matches your package.json configuration:
For ES Modules ("type": "module):
// Correct: ES Module syntax
import express from 'express';
export default myFunction;For CommonJS (no type field or "type": "commonjs"):
// Correct: CommonJS syntax
const express = require('express');
module.exports = myFunction;Solution 2: File Extension Approaches
Node.js supports different file extensions for different module types:
.js- Depends on package.json "type" field.mjs- Always treated as ES module.cjs- Always treated as CommonJS module
You can rename files to enforce module type regardless of package.json:
# ES Module files
mv nuxt.config.js nuxt.config.mjs
# CommonJS files
mv config.js config.cjsSolution 3: Modern Node.js Features (v20.10.0+)
Recent Node.js versions offer additional options:
# Automatic module detection
node --experimental-detect-module index.js
# Set default module type
node --experimental-default-type="module" index.jsAdd these to your package.json scripts for convenience:
{
"scripts": {
"start": "node --experimental-detect-module index.js",
"dev": "node --experimental-default-type=\"module\" index.js"
}
}Solution 4: Runtime Module Type Selection
For special cases like CI/CD pipelines, you can specify module type at execution:
# Execute as ES module without package.json configuration
node --input-type=module -e "import { myFunc } from './module.js'; myFunc();"Best Practices
- Be consistent - Choose one module system for your project
- Update Node.js - Use the latest LTS version for best ES module support
- Use explicit extensions - Consider
.mjs/.cjsfor clarity in mixed projects - Check dependencies - Ensure your dependencies support your chosen module system
WARNING
Removing "type": "module" may solve immediate errors but could break other parts of your code that use ES module syntax. Always check your entire codebase before making this change.
TIP
As of Node.js v16+ (LTS), ES module support is stable and well-tested. Consider migrating to ES modules for future-proofing your code.
Conclusion
The "type": "module" field enables ES module syntax in Node.js. Whether to keep or remove it depends on your project's needs:
- Keep it if you want to use modern
import/exportsyntax - Remove it if you prefer CommonJS
require/module.exportssyntax - Use file extensions (
.mjs/.cjs) for mixed codebases - Leverage Node.js flags for flexibility in newer versions
Choose the approach that best fits your project requirements and team preferences while ensuring consistency throughout your codebase.