Import Syntax and JavaScript Modules

Learn about modules and how to export and import them in JavaScript.

History

Modules in JavaScript are a bit of a special topic. JavaScript modules did not officially exist in the past, but there have been many attempts to introduce them. If you have been part of the development scene for a while, you might remember Asynchronous Module Definition (AMD), and if you have worked with Node.js before, you likely came across CommonJS modules, such as module.exports and require('./myModule').

Note: AMD format is used to create modules in JavaScript and is targeted for use in browsers. This format proposes a particular way of defining modules so that modules and their dependencies can be loaded into the browser asynchronously. There are two key methods that you need to use when creating and consuming AMD modules:

  1. define methods
  2. require methods

The idea is that we create a module using the global define method, and then we can import that module in other parts of the code using the global require method.

On the other hand, in CommonJS, modules are loaded synchronously. We use require() to import modules in CommonJS. When implementing a module for other people to use, we can define exports, either named exports or a default export.

There has been a lot of debate centering on which module standard should become the de-facto standard, what the syntax should look like, and how the implementation should work on the side of the interpreter. In the end, a consensus was reached on using import and export keywords to let the modules communicate with each other.

Babel was the first to implement a solution that was based on the previous standard of the specification. This implementation had to change in between, though, as updates were made to the standard. So when Webpack entered the scene, it implemented yet another mechanism to manage the resolving and loading of JavaScript modules based on the now-approved final standard, just like TypeScript.

After 10 years, we have finally reached a consensus for the specification, and JavaScript engines are busy implementing it. There are still some confusing elements, which is why we should still rely on Webpack, Babel, or TypeScript to work with modules.

We have talked a lot about the history of modules until now. But how do imports work, and what even are modules?

Modules in JavaScript

The primary goal of modules is to encapsulate the JavaScript scope for each module. In this case, a module is actually a single file.

Note: As long as you are not explicitly limiting their scope by using an IIFE, each function, variable, or other code objects you declare in JavaScript is available globally.

Modules restrict the availability of code objects that we declare in JavaScript by making the code in the module only available in the module itself. This can avoid complications, such as two libraries using the same variable. Moreover, modules encourage reusable code without being concerned about using already existing variables or overriding functions that have already been declared.

  1. Modules can export functions, classes, and variables that have been declared within them. Other modules can then import these exports if necessary. To export these functions and variables, we use a special export keyword. To import these, we use the import keyword. Exporting can take two forms:
  • named exports
  • default export

Let’s go through each of these one by one.

Named exports

Assume that we have created a module, calc.mjs, that provides a number of functions for us to make more complicated calculations. For example, the module could contain the following:

export const double = (number) => number * 2;
export const square = (number) => number * number;
export const divideBy = (number, divisor) => number / divisor;
export const divideBy5 = (number) => divideBy(number, 5);

We announce an export by using the export keyword. Then, we declare a variable and assign it an arrow function with one or more parameters. Finally, by directly returning the result, we could use this function elsewhere in another module. Alternatively, we can achieve the same with two separate steps:

const double = (number) => number * 2;
export double;

Using the import keyword, we can now use these functions elsewhere in our application. To do this, we use import followed by the exports that we want to import in curly brackets as well as from and the path to the module. Let’s look at an example.

Get hands-on with 1200+ tech skills courses.