Keywords: Node.js | ES modules | CommonJS | import error | package.json configuration
Abstract: This article provides an in-depth analysis of the common 'SyntaxError: Cannot use import statement outside a module' error in Node.js environments, exploring differences between ES modules and CommonJS module systems, offering multiple solutions including package.json configuration, file extension modifications, Babel transpilation setup, and demonstrating proper module system configuration in ApolloServer projects through practical examples.
Module System Fundamentals
Node.js supports two main module systems: CommonJS and ECMAScript Modules (ES modules). CommonJS uses require() and module.exports syntax, while ES modules employ import and export syntax. Before Node.js 13.2.0, ES module support was experimental and required specific configuration.
Error Cause Analysis
When Node.js encounters an import statement, it checks whether the current file is recognized as an ES module. By default, Node.js treats .js files as CommonJS modules. Without proper configuration, the "Cannot use import statement outside a module" error occurs.
Solution 1: Package.json Configuration
Add the "type": "module" field to your project's root package.json file, which will treat all .js files as ES modules:
{
"name": "my-project",
"version": "1.0.0",
"type": "module",
"dependencies": {
// dependencies
}
}
After configuration, all .js files in your project will use ES module syntax. To keep certain files as CommonJS modules, use the .cjs extension.
Solution 2: File Extension Modification
Another approach is to use the .mjs extension to explicitly identify ES module files:
// server.mjs
import { startServer } from './server.mjs';
startServer();
Files with .mjs extension are always treated as ES modules, while .js files remain as CommonJS modules.
Babel Transpilation Configuration
For projects requiring backward compatibility, use Babel to transpile ES module syntax to CommonJS syntax. First install necessary Babel packages:
npm install --save-dev @babel/core @babel/preset-env @babel/node
Create a .babelrc configuration file:
{
"presets": ["@babel/preset-env"]
}
Then run your code using babel-node:
npx babel-node index.js
TypeScript Project Configuration
In TypeScript projects, properly configure the module system in tsconfig.json:
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"esModuleInterop": true,
"moduleResolution": "node"
}
}
Setting module to "commonjs" ensures TypeScript compiles to Node.js-compatible CommonJS modules.
Practical Case Analysis
In ApolloServer projects, if index.js mixes require and import, unify the module system. Here's a correct configuration example:
// package.json
{
"type": "module",
"dependencies": {
"apollo-server": "^2.9.6",
"dotenv": "^16.0.0"
}
}
// index.js
import 'dotenv/config';
import { startServer } from './server.js';
startServer();
Environment Compatibility Considerations
Ensure your Node.js version supports ES modules. Node.js 13.2.0+ provides stable ES module support. Check your Node.js version with:
node --version
If the version is too old, upgrade to the latest LTS version.
Testing Environment Configuration
In Jest testing environments, additional configuration is needed to support ES modules. Add to jest.config.js:
module.exports = {
testEnvironment: 'node',
transform: {},
extensionsToTreatAsEsm: ['.js'],
globals: {
'ts-jest': {
useESM: true
}
}
};
Deployment Environment Considerations
Different deployment platforms (like Netlify, Vercel) may require specific configurations. For example, in Netlify, add to netlify.toml:
[functions]
node_bundler = "esbuild"
This ensures functions are properly bundled for ES modules.
Best Practice Recommendations
1. Clearly choose a module system at project inception, avoid mixing systems
2. For new projects, recommend using ES modules with "type": "module" configuration
3. For existing project migration, gradually change files to .mjs extension
4. Ensure all team members use the same Node.js version and configuration
5. Regularly update dependencies to maintain compatibility