JavaScript modules: The real difference between `import`, `require` and `import()`
Tags: javascript, webdev, node, programming
Published: 2022-06-04 12:24:56

## Introduction

I'm a bit ashamed to admit it but I didn't know (or care) about the difference of how `import` and `require` worked under the hood until recently. 

- I knew `import` was part of ES6 and both can be used for consuming JavaScript files. 
- I also knew that the syntax was different and I preferred Import's simpler syntax, but didn't think twice beyond that. 

I guess I should've been a bit more inquisitive, but frankly I didn't really feel like I needed to know.

But this changed recently while I was playing around with the new React suspense and lazy loading APIs. I stumbled upon the requirement to use `import()`. I started having questions about the difference between the various ways we can import and consume modules.

So here goes:

## Require

This is the old way of consuming JavaScript files. It was introduced in 2009 and is part of commonJS - a module (AKA 'file') formatting system. It became a built-in function in nodeJS.

- Require is **just a function**. It takes a string path and returns whatever is being exported from the specified path.

- Being a function, it **can be dynamically used** inside of other functions or nested blocks like `if` statements.

- It is **processed at run-time**, like any other function.

- Modules **loads synchronously**. Which is great server-side but not for front-end, which is why Webpack applies bundle magic to wrap `require`'d code inside of a IIFE (I am underplaying the complexity and I still don't 100% get this part but that is my TL;DR understanding).

## ES6 import 

This is the [modern syntax introduced in JavaScript ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).

- It is static, meaning that exports are known at **build-time**. This means that you cannot run imports conditionally.

- All imports are **hoisted** (moved to the top of their scope prior to execution) regardless of where you write this.

- As they live on the top level of the scope, `import` cannot be nested.

- The static nature of ES6 import allows static analysis. This results in modules being imported to be analysed with static analysis tools. This in turn allows optimisations such as '[tree-shaking](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking)'.

## Using import as a function

While `import` is great, there are situations where we want to load modules dynamically.

For example, when using [React suspense we want to dynamically load a module only when it is ready using the `lazy` API](https://reactjs.org/docs/code-splitting.html). We can't use `import` to do this. 

```
import {lazy} from React

// Import here wouldn't run.
const loadLazyModule = lazy(() => {
    import thisModuleWontWork from 'myModule';
}) 
```

For this situation you can use the [`import` keyword as a function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports) ie. `import()`

- It allows us to **dynamically load** the module.

- It allows this by returning a promise that resolves into the module object which contains its exports.

- This expression can be called from anywhere in our code.

This is how we can use this with React's `lazy` API.

```
import {lazy} from React

// Using the import() expression we can load modules dynamically
const loadLazyModule = lazy(() => import('myModule')) 
```

## Takeaways

In a nutshell, all three work differently - it isn't just a matter of syntax.

- `require` is a function that is evaluated modules at run-time.
- `import` is a static syntax that evaluates modules at build-time.
- `import()` is a function that allows us to dynamically load modules.

## Great resources on the topic:
- [Stack overflow thread on the differences](https://stackoverflow.com/questions/46677752/the-difference-between-requirex-and-import-x)
- [Youtube video on the difference between `require` and `import`](https://www.youtube.com/watch?v=mK54Cn4ceac&t=404s)
- This [amazing intense article](https://ui.dev/javascript-modules-iifes-commonjs-esmodules) by Tyler McGinnis on JavaScript Modules