Friday, November 26, 2021

JavaScript require vs import

 In this article let us understand what JavaScript require() and import() statements do, how they fetch modules, and their differences. We will begin by understanding what a JavaScript module is, in the first place.


JavaScript module is a file that contains a few lines of code written in JavaScript. They are the same as JavaScript Libraries. Modules often contain a class or a library of functions that are used for a specific purpose. These can be called with the help of require and import statements. The use of modules reduces the number of lines of code in one’s program/script. A major advantage of modules is that functions of another module can be called without writing the body of the functions themselves.

Some of the common modules are:

CommonJS, AMD, RequireJS, ES(ECMAScript)6 Modules. Refer to this medium article for an in-depth explanation of how these modules are different.

Table of Contents


Syntax and explanation

1) require()

In NodeJS, require() is a built-in function to include external modules that exist in separate files. require() statement basically reads a JavaScript file, executes it, and then proceeds to return the export object. require() statement not only allows to add built-in core NodeJS modules but also community-based and local modules.

Syntax:

To include a module, the require() function is used with the name of the module:

var myVar = require('http'); //to use built-in modules

Var myVar2 = require('./myLocaModule') to use local modules


2) import()

import() & export() statements are used to refer to an ES module. Other modules with file types such as .json cannot be imported with these statements. They are permitted to be used only in ES modules and the specifier of this statement can either be a URL-style relative path or a package name. Also, the import statement cannot be used in embedded scripts unless such script has a type="module". A dynamic import can be used for scripts whose type is not “module”

Syntax:

var myVac = import("module-name");

How is require() different from import()

One of the major differences between require() and import() is that require() can be called from anywhere inside the program whereas import() cannot be called conditionally, it always runs at the beginning of the file.

To use the require() statement, a module must be saved with .js extension as opposed to .mjs when the import() statement is used.

ES modules can be loaded dynamically via the import() function unlike require().

javascript export import Module Cheatsheet

export const name = 'value'
import { name } from '...'

// Default Export | Default Import
export default 'value'
import anyName from '...'

// Rename Export | NameImport
export { name as newName }
import { newName } from '...'

// Name + Default | Import All
export const name = 'value'
export default 'value'
import * as anyName from '...'

// Export List + Rename | Import List + Rename
export {
  name1,
  name2 as newName2
}
import {
  name1 as newName1,
  newName2
} from '...'

Now let's look at each of them and see how they work 🤓

#a. Name

The key here is having a name. Hence a "named" export lol 😂

export const name = 'value';
import { name } from 'some-path/file';

console.log(name); // 'value'

❌ What did I say, no name, no export!

export 'value'

import { } // 👈 see I don't even know what to put here...give me a name!

#b. Default

With a default export, you don't need any name. Because you can name it whatever you want 👏

export default 'value'
import anyName from 'some-path/file';

console.log(anyName); // 'value'

❌ No Variable Declaration with Default

export default const name = 'value'; // don't try to give me a name!

#Mixing Default + Name

You can absolutely combine default and name export in one file 🤝

export const name = 'value';
export default 'value'
import anyName, { name } from 'some-path/file';

#c. Export List

The third style is an Export List.

const name1 = 'value1';
const name2 = 'value2';

export {
  name1,
  name2
}
import {
  name1,
  name2
} from 'some-path/file'

console.log(
  name1, // 'value1'
  name2, // 'value2'
)

One important thing to note is that these lists are NOT objects. Yes, I know it looks like it. But it isn't. I made this confusion when I first learned modules. It's not an object, it's an export list!

// ❌ Export list ≠ Object
export {
  name: 'name'
}

#Renaming Export

Not happy with the export name. No problem, you can rename it using the as keyword.

const name = 'value'

export {
  name as newName
}
import { newName } from 'some-path/file'

console.log(newName); // 'value'

// Original name is not accessible
console.log(name); // ❌ undefined

❌ Can not combine inline export with export list

export const name = 'value';

// You're already exporting name ☝️, don't export me again
export {
  name
}

#Renaming Import

The same rule applies to import. We can rename it using the as keyword.

const name1 = 'value1';
const name2 = 'value2';

export {
  name1,
  name2 as newName2
}
import {
  name1 as newName1,
  newName2
} from '...'

console.log(newName1); // 'value1'
console.log(newName2); // 'value2'

❌
name1; // undefined
name2; // undefined

#Import All

export const name = 'value';

export default 'defaultValue';
import * as anyName from 'some-path/file';

console.log(anyName.name); // 'value'
console.log(anyName.default); // 'defaultValue

Examples

Using named exports

In a module my-module.js, we could include the following code:

// module "my-module.js"
function cube(x) {
  return x * x * x;
}

const foo = Math.PI + Math.SQRT2;

var graph = {
  options: {
      color:'white',
      thickness:'2px'
  },
  draw: function() {
      console.log('From graph draw function');
  }
}

export { cube, foo, graph };

Then in the top-level module included in your HTML page, we could have:

import { cube, foo, graph } from './my-module.js';

graph.options = {
    color:'blue',
    thickness:'3px'
};

graph.draw();
console.log(cube(3)); // 27
console.log(foo);    // 4.555806215962888