DEV Community

Yash Solanki
Yash Solanki

Posted on • Updated on

require vs import in NodeJs

Introduction

If you’re a NodeJs developer, you might have come across some code snippets which use require() to import modules while others use import for the same purpose; which might have got you to wonder, which one of these is correct and which should you use in your project?

In this article, we’ll try to answer all such questions and clear the air around the difference between both the import techniques.

Scope

  • This article will walk you through the difference between the two import techniques in NodeJS, or, in general, the difference between the two module systems which use these import techniques.
  • This article does not cover the difference in syntax for default, named, and mixed exports in both the module systems.

Modules and Module systems

  • Module systems enable us to structure and organize different modules in our Javascript code
  • By default, Node uses CommonJS, while ES Modules is the Javascript official standard for writing reusable code on both client and server.

As we are already aware, each file in Node is treated as a separate module.

A module is a Javascript file containing related code. So as our application gets bigger, we can split it into different files viz. modules, which makes our code more readable and also allows us to reuse the code in different parts of our application

The code inside these modules is not available globally i.e. you cannot directly access the variables, functions, and classes defined in one module in any other module.

Instead, we have to explicitly tell NodeJS which parts of a module must be exported and which parts must be imported into a file. The module system helps us to structure and organize these modules.

In this article, we’ll try to understand two commonly used module systems - CommonJS and ECMAScript or ES Modules.

CommonJS vs ES Modules

require is used to import modules in CommonJS while import is used in ES Modules.

Since require and import are just small parts of two different module systems, it makes more sense to differentiate between CommonJS and ES Modules to get a larger picture.

CommonJS (Uses require for importing modules)

  • CommonJS is the legacy module system implemented by NodeJS. In CommonJS, we can export modules using module.exports and import them using require
  • We can import various built-in modules, third party modules (installed via npm), or any of our local modules using require
//calculate.js
function add(num1, num2) {
    return num1 + num2;
}

function subtract(num1, num2) {
    return num1 - num2;
}

module.exports = {add, subtract};

//index.js
const { add, subtract } = require('./calculate');

console.log(add(1, 2)); // 3
console.log(subract(3, 2)); // 1
Enter fullscreen mode Exit fullscreen mode

ES Modules (Uses import for importing modules)

  • While Javascript did not have any built-in module system in the beginning, Node used CommonJS as its default module system
  • But, in ES2015 (also commonly known as ES6), Javascript got its own module system - ES Modules, which has been widely adopted ever since, and NodeJs also added support for the same.
  • We can use ES Modules instead of the default CommonJS module system in Node by either

    • Changing the extension of the file from .js to .mjs

      • So, in the example above, if we change the extension of the files to .mjs, we can use the ES6 syntax for importing and exporting modules

        //calculate.mjs
        
        function add(num1, num2) {
            return num1 + num2;
        }
        
        function subtract(num1, num2) {
            return num1 - num2;
        }
        
        export { add, subtract };
        
        //index.mjs
        import { add, subtract } from './calculate.mjs';
        
        console.log(add(1, 2)); // 3
        console.log(subract(3, 2)); // 1
        
    • Or instead of changing the file extension, we can also add a property "type": "module" at the top-level of package.json to use ES Modules across our Node application

    {
      "name": "nodejs-app",
      "dependencies": {
        ...
        }
    
        "type": "module"
    }
    

Difference between CommonJS and ES Modules

  • CommonJS modules can be imported at any place in the program while ES modules have to be imported only at the beginning of the program

    const express = require('express');
    
    function getData() {
        const data = require('./data');  //This is valid
        //Do Something
    }
    
    
  • Since CommonJS modules are imported dynamically at runtime, module bundlers like webpack cannot remove unused modules from the production build, thus increasing the size of the bundle

  • CommonJs modules are loaded synchronously, which means that the modules are processed one by one, which can cause performance issues in large scale applications. ES Modules, on the other hand, are imported asynchronously, thus offering performance benefits as the application scales

  • Widely used CommonJs variables like __dirname , __filename and NODE_PATH ********are not available in ES Modules

  • ES Modules is the official standard and most of the frontend frameworks like React, Vue etc use it, so it offers consistency in client and server side code

Which one should you use?

  • If you want consistency in the backend and frontend, you should consider using ES Modules as it is the official standard for Javascript.
  • Node v9 or below versions do not support ES modules. Though it’s very unlikely, but if you’re working on a project with these node versions, you won’t be able to use ES Modules
  • In conclusion, it doesn’t matter if you’re using CommonJS or ES Modules as long as you’re confident with the choice.

Top comments (4)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Nice stuff. Couple of clarifications:

  • You can import JSON with ES module syntax in both the browser and NodeJS. Like this:
import myJson from './myJson.json'; // Browser version.

import myJson from './myJson.json' assert { type: 'json' }; // NodeJS version.
Enter fullscreen mode Exit fullscreen mode
  • You can dynamically and conditionally import ES modules with the dynamic import syntax. Looks like a function but is not.
async function myDynConfig() {
    const { default: wjConfig, Environment } = await import('wj-config');
    ...
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
yksolanki9 profile image
Yash Solanki

@webjos I'm glad that you liked the article, and thanks for taking out time to point some issues.
Just wanted add some more details about Import assertions - Yes, TC39 has been planning to include Import Assertions, but the proposal is still in stage 3 - ref. So it'll be added to the specs soon, but is not live yet.
Anyways, I'll add both the points you mentioned in the article. Thanks again!

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

It is actually live in NodeJS v18.

Thread Thread
 
yksolanki9 profile image
Yash Solanki

Have edited the article. Thanks!