others-how to solve can not import error in nodejs?

1. Problem

Sometimes, when we want to run our node.js application, we got this error:

➜  simple_websocket_server git:(master) ✗ node app.js          
(node:6545) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/bswen/lua-projects/kong-plugin/server/simple_websocket_server/app.js:1
import { WebSocketServer } from 'ws';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47
➜  simple_websocket_server git:(master) ✗ node --version
v16.13.1
➜  simple_websocket_server git:(master)

The core error message is :

import { WebSocketServer } from 'ws';
^^^^^^

SyntaxError: Cannot use import statement outside a module

It means we can not use import to import module from outside a module.



The code that cause the above error is as follows:

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 18080 });

wss.on('connection', function connection(ws) {
    ws.on('message', function message(data) {
        console.log('received: %s', data);
    });

    ws.send('something');
});



The package.json is as follows:

{
  "name": "simple_websocket_server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ws": "^8.6.0"
  }
}



2. Solution

add

 "type": "module"

to package.json, the result package.json is as follows:

{
  "name": "simple_websocket_server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ws": "^8.6.0"
  }
}



3. Why does it work?

3.1 What is a module in node.js?

In Node. js, Modules are the blocks of encapsulated code that communicates with an external application on the basis of their related functionality. Modules can be a single file or a collection of multiples files/folders.

When learning the node.js , you’ll find that it has modules in two formats. One is the ES6 module, referred to as ESM; the other is the CommonJS module dedicated to Node.js, referred to as CJS. The two modules are not compatible.

ES6 modules are very different from CommonJS modules.CommonJS modules use require() to load and module.exports output, ES6 modules use import and export.

require() is synchronous loading, and the following code must wait for the command to be executed before it is executed. The import command is loaded asynchronously, or to be more precise, ES6 modules have a separate static analysis phase, the analysis of dependencies is done in that phase, and the bottom-level module is executed first.

Quote from https://nodejs.org/api/esm.html#esm_enabling:

Node.js has two module systems: CommonJS modules and ECMAScript modules.Authors can tell Node.js to use the ECMAScript modules loader via the .mjs file extension, the package.json “type” field, or the –input-type flag. Outside of those cases, Node.js will use the CommonJS module loader. See Determining module system for more details.



4. Summary

In this post, I demonstrated how to solve the SyntaxError: Cannot use import statement outside a module error when trying to run a nodejs application. The key point is to distinguish the module system in nodejs, If you are importing in old applications, please specifty the type=module in your package.json That’s it, thanks for your reading.