Resolving 'Cannot use import statement outside a module' Error in Node.js

Oct 21, 2025 · Programming · 28 views · 7.8

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

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.