Understanding the Import Error
When developing with Node.js, specifically using NestJS and TypeORM, encountering the error ‘Cannot use import statement outside a module’ might be confusing. This error is commonly caused by a mismatch between the ECMAScript module (ESM) and CommonJS (CJS) module systems within your Node.js application. JavaScript initially used the CommonJS system, which is fine for server-side JavaScript, but it does not support the import
statement directly. On the other hand, ESM is the official standard for packaging JavaScript code and is well-supported in browsers, allowing the use of the import
and export
syntax.
Updating Your Configuration
The primary solution is to ensure that both Node.js and your project configuration files correctly handle ESM syntax. With Node.js embracing ESM, you should ensure your Node.js version is up to date. After that, check your TypeScript configuration. NestJS uses TypeScript, which has its configuration file tsconfig.json
. This file should be edited to include "module": "commonjs"
which allows TypeScript to compile import
statements into require
statements which are supported by CommonJS. In addition, you need to specify "moduleResolution": "node"
to inform TypeScript how to look up module files.
If your application is meant to use the ESM syntax, then you should ensure your project’s package.json
has the type set to ‘module’ by including "type": "module"
. This might require you change your file extensions from .js
to .mjs
to clarify that these scripts use ESM syntax.
Correcting Source Code and Project Structure
Beyond configuration, it’s also necessary to ensure that your source code is using the correct module syntax. In a NestJS project, the source files should typically use import
and export
without any issue, as it compiles its TypeScript code to be compatible with Node.js’s module system. However, any raw JavaScript files in your project should also use the module.exports
and require
syntax if you’re sticking with CommonJS, or use the .mjs
extension and import/export
if you’re using ESM.
Running with the Correct Settings
Execution semantics can also cause this error if Node.js is not running the compiled JavaScript with the correct module logic. If you are intentionally using the ECMAScript module system with a .mjs
extension or the "type": "module"
in your package.json
, you’ll need to run Node.js with the flag --experimental-modules
for versions prior to Node.js 14. From version 14 and onward, Node.js has stable support for ECMAScript modules without this flag.
Working Code Example
Below is an example NestJS controller which should compile and run without the ‘Cannot use import statement outside a module’ error if the above fixes have been applied:
import { Controller, Get } from '@nestjs/common';
@Controller('hello')
export class HelloController {
@Get()
getHello(): string {
return 'Hello World!';
}
}
Make sure you have the following configuration in your tsconfig.json
:
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node"
}
}
If this is an ESM project, your package.json
might look like this:
{
"type": "module",
...
}
And to run your NestJS project with Node.js 14 or later:
node your-app-entry-file.js
Or with an older version of Node.js, use:
node --experimental-modules your-app-entry-file.mjs
Note that for an actual fix you will need to adapt these examples to your specfic project’s file names and structures.