nodejsnotes

Topic 007: Difference between require() and import in Node.js

Topic 007: Difference between require() and import in Node.js

In Node.js, both require() and import are used to include modules, but they belong to different module systems and have distinct differences.

  1. require(): This function is part of the CommonJS module system, which is the default module system in Node.js. CommonJS modules are synchronous and are typically used in Node.js environments.

  2. import: This statement is part of the ES6 (ECMAScript 2015) module system, also known as ECMAScript modules (ESM). ESM modules are asynchronous and are the standard for JavaScript modules in modern environments, including browsers and Node.js (starting from version 12 with the --experimental-modules flag, and natively in later versions).

Using require()

Here’s an example of how to use require():

moduleA.js

module.exports = function () {
  console.log("Hello from moduleA");
};

main.js

const moduleA = require("./moduleA");
moduleA();

Using import

Here’s the equivalent example using import:

moduleA.mjs

export function greet() {
  console.log("Hello from moduleA");
}

main.mjs

import { greet } from "./moduleA.mjs";
greet();

Key Differences

  1. Syntax:

    • require(): const module = require('module');
    • import: import { something } from 'module';
  2. Default vs Named Exports:

    • With require(), you typically export a single entity using module.exports, and import it with const something = require('./module');.
    • With import, you can export multiple named entities and import them selectively: export const foo = ...;, import { foo } from './module';.
  3. Dynamic Loading:

    • require() can be called conditionally, allowing for dynamic loading of modules.
      if (condition) {
        const moduleA = require("./moduleA");
        moduleA();
      }
      
    • import statements are static and must be declared at the top level of the file. However, dynamic imports can be done using import() function.
      if (condition) {
        import("./moduleA").then((moduleA) => {
          moduleA.greet();
        });
      }
      
  4. Execution Context:

    • CommonJS modules (require()) are executed in the scope of their own file, allowing for private variables and functions.
    • ES Modules (import) are executed in strict mode and support top-level this binding to undefined.
  5. Compatibility:

    • require() is fully supported in Node.js for all versions.
    • import is supported in Node.js from version 12.0.0 with a flag and natively from version 13.2.0 without the flag. It is also widely supported in modern browsers.
  6. File Extensions:

    • By default, .js files are treated as CommonJS modules and .mjs files as ES modules in Node.js.
    • You can use a package.json with a "type": "module" field to indicate that .js files should be treated as ES modules.

Example with package.json

package.json

{
  "type": "module"
}

moduleA.js

export function greet() {
  console.log("Hello from moduleA");
}

main.js

import { greet } from "./moduleA.js";
greet();

By setting "type": "module" in package.json, .js files are interpreted as ES modules, allowing you to use import/export syntax directly without needing the .mjs extension.