ES Modules or CommonJS: What's the Deal and Why Should I Care ?
Tags: javascript, webdev, node, beginners
Published: 2023-05-10 10:53:12

Today, I'm on a quest to untangle a little confusion that's been bothering me (as a JS noob 👶)- and maybe you, too. 

It's all about JavaScript module systems: [ES Modules](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) and [CommonJS](https://en.wikipedia.org/wiki/CommonJS). Funny enough, I stumbled upon this while trying out a library, [@dozerjs/dozer](https://github.com/getdozer/dozer-js), a JavaScript library to interact with [Dozer](https://github.com/getdozer/dozer), a data API backend.

Alright, here's the deal. Back in the day, JavaScript didn't have a built-in module system. So, dev's couldn't easily separate their code into different files or manage dependencies. It was kind of a mess. But then, Node.js stepped up with its own module system, CommonJS. And later, [ES6 (ES2015)](https://262.ecma-international.org/6.0/) introduced ES Modules.

Now, you might be thinking, **"Why should I, as a web dev, even care about this? 🤔"** Well, it's simple. The module system you choose can affect your code's structure, how fast it runs, and even its compatibility. Trust me, I learned this the hard way when I faced some import issues while running a node app with [@dozerjs/dozer](https://github.com/getdozer/dozer-js). Let's dive in!

**CommonJS**: This is like the godfather of JavaScript module systems. It uses the `require()` function to import modules and `module.exports` to export them. 
> **_The cool part?_** You can use `require` pretty much anywhere - inside functions, loops, or based on some conditions. 
> **_The not-so-cool part?_** Imports are synchronous, meaning they could slow things down a bit.

Here's a little example:

```javascript
// Importing a module
const express = require('express');

// Exporting a module
module.exports = someFunction;
```

**ES Modules**: These are the new kids on the block, coming in with ES6. Instead of `require()` and `module.exports`, they use `import` and `export`. These modules are statically analyzed, which means the imports and exports are determined before the code runs. This can make your code run faster and gives you some extra tooling perks.

Here's how it looks:

```javascript
// Importing a module
import express from 'express';

// Exporting a module
export default someFunction;
```

## So, which one do you choose? 🤹‍♀️**

If you're writing code for the browser, ES Modules are a great choice because modern browsers support them natively. For Node.js, it does support ES Modules, but you might still find yourself using CommonJS for compatibility reasons. 

Got some older browsers or Node.js versions to support? They might not be fans of ES Modules. In that case, you could stick with CommonJS or use a tool like [Babel](https://babeljs.io/) to compile your ES Modules to CommonJS. 

The trend is definitely leaning towards ES Modules, but there's still a ton of CommonJS code out there. So, it's a good idea to know your way around both. 

Remember, the choice is yours. Pick the module system that fits your project and team the best.

## A Quick Example: Switching to CommonJS in Node.js

I thought it might be handy to wrap this up with a little example. So, let's say you're working on a Node.js app and you've been using ES Modules. And if want to switch back to CommonJS. **How do you do it?**

Well, first, you'll need to change your import and export statements. Here's an example:

```javascript
// ES Module import
import express from 'express';

// Change to CommonJS require
const express = require('express')
```

But wait, there's another step! You also need to update the type in your `package.json` file. If you have `"type": "module"`, which allows you to use ES Modules, you'll want to remove it to switch back to CommonJS.

Here is the `package.json` example:
```json
{
  "name": "dozer_lib_js_test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "type": "commonjs",
  "dependencies": {
    "@dozerjs/dozer": "^0.0.6"
  }
}
```

I hope this helps!