> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/js/module/es-vs-commonjs.md).

# ES vs CommonJS

[JS](/web/js.md) ⟩ [module](/web/js/module.md) ⟩ ES vs CommonJS

{% hint style="success" %}
(<mark style="color:yellow;">**Node.js**</mark>)&#x20;

* <mark style="color:yellow;">**ES modules**</mark> can <mark style="color:blue;">`import`</mark> <mark style="color:yellow;">**ES**</mark> or <mark style="color:yellow;">**CommonJS**</mark> module exports.
* <mark style="color:yellow;">**CommonJS modules**</mark> can <mark style="color:red;">**only**</mark> <mark style="color:blue;">`require`</mark> <mark style="color:yellow;">**CommonJS**</mark> module exports.

```javascript
// (package.json in Node.js) 
"type": "module"      // ES module
"type": "commonjs"    // CommonJS module (⭐️ default)

                    ES export    CommonJS export
-------------------------------------------------
ES import           ✅           ✅
CommonJS require    ❌           ✅ 
-------------------------------------------------
⭐️ looks like CommonJS "module.exports" is a better choice❓ 
```

{% endhint %}

{% tabs %}
{% tab title="🧨 雷區" %}
{% hint style="danger" %} <mark style="color:yellow;">**module path name**</mark>

```javascript
const obj = require(`./${name}`);    // require: can be dynamic
import {obj} from './module.js';     // import: must be string literal
```

{% endhint %}

{% hint style="danger" %} <mark style="color:yellow;">**file name extension**</mark>

```javascript
// require: can leave out .js when importing a local module.
require("./module")                 // ✅ works

// import: won't work without .js
import module from "./module"       // ❌ won't work
import module from "./module.js"    // ✅ works
```

{% endhint %}

{% hint style="warning" %} <mark style="color:yellow;">**execution order**</mark>

* <mark style="color:blue;">`require`</mark> (expression) - runs inline, after the code above it.&#x20;
* <mark style="color:blue;">`import`</mark> (statement) - runs before the rest of the script.\
  (note: import expressions can be dynamic.)
  {% endhint %}
  {% endtab %}

{% tab title="⭐️ 重點" %}
{% hint style="danger" %}
(<mark style="color:yellow;">**Node.js**</mark>) in an **ES module** (.mjs / .js of "type":"module")：

* <mark style="color:green;">**can**</mark>**&#x20;**<mark style="color:yellow;">**only**</mark> use <mark style="color:blue;">`import`</mark> / <mark style="color:blue;">`export`</mark> .&#x20;
* <mark style="color:green;">**can**</mark>**&#x20;**<mark style="color:yellow;">**import**</mark> **CommonJS** exports.
* <mark style="color:red;">**cannot**</mark> use <mark style="color:blue;">`require`</mark>.

```javascript
// (in Node.js) "type": "module"
import {str} from './es.mjs';          // .mjs - es module
import {obj} from './commonjs.cjs';    // .cjs - commonjs module
```

{% endhint %}

{% hint style="danger" %}
(<mark style="color:yellow;">**Node.js**</mark>) in an **CommonJS module** (.cjs / .js of "type":"commonjs")：

* <mark style="color:red;">**cannot**</mark> use <mark style="color:blue;">`require`</mark> to <mark style="color:red;">**load**</mark> an <mark style="color:yellow;">**ES module**</mark>.
  {% endhint %}

{% hint style="info" %}
(<mark style="color:yellow;">**Node.js**</mark>)

* <mark style="color:yellow;">**`.cjs`**</mark> -> CommonJS module.
* <mark style="color:yellow;">**`.mjs`**</mark> -> ES module.
* <mark style="color:red;">**`.js`**</mark>&#x20;
  * "type":"module"  ->  ES module.
  * "type":"commonjs"  ->  CommonJS module.
    {% endhint %}

{% hint style="warning" %}
(in browser)

* <mark style="color:red;">**cannot**</mark> use <mark style="color:blue;">`require`</mark>.
* <mark style="color:red;">**cannot**</mark>**&#x20;**<mark style="color:yellow;">**import**</mark> **CommonJS** exports.
* <mark style="color:green;">**can**</mark>**&#x20;**<mark style="color:yellow;">**only**</mark> use <mark style="color:yellow;">**ES**</mark> <mark style="color:blue;">`import`</mark> / <mark style="color:blue;">`export`</mark> .&#x20;
  {% endhint %}
  {% endtab %}

{% tab title="👥 相關" %}

* [module pattern](/web/js/module/module-pattern.md)
* [ES module](/web/js/module/es.md)
  {% endtab %}

{% tab title="📗 參考" %}

* [x] [The three differences between require and import in Node.js](https://pencilflip.medium.com/the-three-differences-between-require-and-import-in-node-js-f54f78f5936f)
* [x] [Using ES modules with CommonJS modules in Node.js](https://pencilflip.medium.com/using-es-modules-with-commonjs-modules-in-node-js-1015786dab03)
* [ ] [Using ES modules with CommonJS modules in the browser](https://pencilflip.medium.com/using-es-modules-with-commonjs-modules-in-the-browser-8060fdf13e3d)
  {% endtab %}
  {% endtabs %}
