Introduction to Node modules and ES Modules.

In one project I’m working on, we have migrated from a non-standard building tool to Webpack. This change has allow us to use a standard module system to import/export our code instead of the legacy builder we were using to just concatenate code.

Why is useful to use Javascript Modules?

Javascript modules are needed to maintain the principles of encapsulation and dependency.

As a project grows, it is useful to reuse pieces of software developed in isolation. When one of these pieces of software is brought into a project, a dependency between them is created. For example, many projects nowadays relay in some JS framework like Angular, ReactJS, VueJS or others. This concept is known as dependency.

When a dependency is created between these pieces of software it is of importance that no conflicts arise. This is known as encapsulation. Encapsulation is important because it isolates and guarantees that there won’t be any interference between different pieces of code.

Node module system

NodeJS developers intended to follow CommonJS specifications for module requirement but they changed their mind and implemented its own module system. That’s why Node module system is quite influenced by CommonJS.

NodeJS expose two different elements to interact with the module system: require and module.exports.

The element require is a synchronous function that receives the name of the module, looks for the module in the node_modules folder and returns its main file.

The element module.exports is an special Object that indicates what is exported from a file.

Pros:

  • Creating an dependency is straight forward.
  • Developers don’t have to worry about the loading order. The tree dependency is managed by the module system.
  • The function require may be called anywhere and it may be used dynamically.

Cons:

  • Browsers need a transpolar to support this
  • Synchronous loading is not suitable for client side execution

ES Modules

ES Modules is the ECMA specification for browsers included in the ECMAScript 2015. This specification defines two main elements: import and export.

import is a directive that creates a dependency from another piece of code. It may be used in many different ways and it works both synchronously and asynchronously, but it doesn’t support dynamic loading.

export directive works like module.exports indicating what it is going to be exported from a file. It may be configured in many different ways too.

Pros:

  • It may be used in new browsers directly. Not supported everywhere.
  • Allows both sync/async loading
  • It handles the dependency tree and allows tree shaking.

Cons:

  • Modules can’t be loaded dynamically

Conclussion

Node module system and ES Modules are two different specifications for module management in Javascript. They are usually used together and we must thought carefully which one we should use. For example, if you are on client side, you should go with import/export, otherwise use require/module.exports.

There is a proposal for dynamic import in ES Modules but until that, we may need to use require in client side at some points. This is not a problem because the code should be transpiled anyway since ES Modules are not supported on every browser yet.

Further reading

Mentions: