Finding Node.js modules using require and import

Obviously require is used in CommonJS modules, and import is used in ES6 modules, but there are some details to go over. We’ve already discussed the format and filename differences between CommonJS and ES6 modules, so let’s focus here on loading the modules.

The require function is only available in CommonJS modules, and it is used for loading a CommonJS module. The module is loaded synchronously, meaning that when the require function returns, the module is completely loaded.

By default, a CommonJS module cannot load an ES6 module. But as we saw with the simple-dynamic-import.js example, a CommonJS module can load an ES6 module using import(). Since the import() function is an asynchronous operation, it returns a Promise, and we, therefore, cannot use the resulting module as a top-level object. But we can use it inside a function:

module.exports.usesES6module = async function() {

const es6module = await import(‘./es6-module.mjs’);

return es6module.functionCall();


And at the top-level of a Node.js script, the best we can do is the following:


.then(simple2 => {




console.log(‘count = ${simple2.default()}’);

console.log(‘Meaning: ${simple2.meaning}’);


.catch(err => {



It’s the same as the simple-dynamic-import.js example, but we are explicitly handling the Promise returned by import() rather than using an async function. While we could assign simple2 to a global variable, other code using that variable would have to accommodate the possibility the assignment hasn’t yet been made.

The module object provided by import() contains the fields and functions exported with the export statements in the ES6 module. As we see here, the default export has the default name.

In other words, using an ES6 module in a CommonJS module is possible, so long as we accommodate waiting for the module to finish loading before using it.

The import statement is used to load ES6 modules, and it only works inside an ES6 module. The module specifier you hand to the import statement is interpreted as a URL.

An ES6 module can have multiple named exports. In the simple2.mjs we used earlier, these are the functions next, squared, and hello, and the values meaning and nocount. ES6 modules can have a single default export, as we saw in simple2.mjs.

With simpledemo2.mjs, we saw that we can import only the required things from the module:

import { default as simple, hello, next } from ‘./simple2.mjs’;

In this case, we use the exports as just the name, without referring to the module: simple(), hello(), and next().

It is possible to import just the default export:

import simple from ‘./simple2.mjs’;

In this case, we can invoke the function as simple(). We can also use what’s called a namespace import; that is similar to how we import CommonJS modules:

import * as simple from ‘./simple2.mjs’;






In this case, each property exported from the module is a property of the named object in the import statement.

An ES6 module can also use import to load a CommonJS module. Loading the simple.js module we used earlier is accomplished as follows:

import simple from ‘./simple.js’;




This is similar to the default export method shown for ES6 modules, and we can think of the module.exports object inside the CommonJS module as the default export. Indeed, the import can be rewritten as follows:

import { default as simple } from ‘./simple.js’;

This demonstrates that the CommonJS module.exports object is surfaced as default when imported.

We’ve learned a lot about using modules in Node.js. This included the different types of modules, and how to find them in the file system. Our next step is to learn about package management applications and the npm package repository.

Source: Herron David (2020), Node.js Web Development: Server-side web development made easy with Node 14 using practical examples, Packt Publishing.

Leave a Reply

Your email address will not be published. Required fields are marked *