CommonJS & ES module


Posted by TempuraEngineer on 2022-03-04

ES module(ESM) 與 CommonJS比較

ES module CommonJS
類型 ES6官方標準 Node.js的預設標準
可運行環境 瀏覽器、Node(v13.2.0開始) Node
輸出語法 export default module.exports
引入語法 import ... from '...' require('...')
引入類型 非同步 同步
靜態引入 〇(只能在module頂層出現)
動態引入
修改導出的值
但可能造成變數汙染
重複引入同module 都會運行 只會在第一次加載運行


JS環境

ESM

  • default導出時,default引入

          export default(a, b) => {
              return a + b;
          }
    
          // 因為是default,所以可以自己命名
          imoprt abc from '../src/index.js';
    
  • 多個導出時,只引用其中一個

          export const sum(a, b) => {
              return a + b;
          }
    
          export const getDate(str) => {
              const regex =  /(?<=[0-9]{4}-)[0-9]{2}-[0-9]{2}/;
              return str.match(regex);
          }
    
          import {sum} from '../src/index.js';
    
  • 多個導出時,引入全部

          export const sum(a, b) => {
              return a + b;
          }
    
          export const getDate(str) => {
              const regex =  /(?<=[0-9]{4}-)[0-9]{2}-[0-9]{2}/;
              return str.match(regex);
          }
    
          // 可以自己命名
          import * as utils from '../src/index.js';
    
  • 混合導出時

          export const sum(a, b) => {
              return a + b;
          }
    
          export default(a, b) => {
              return a * b;
          }
    

    混合引入

          // 這邊的abc是export default那個
          import abc, {sum} from './src/index.js';
    

    全部當作一個module引入

          // 這邊的abc是兩個module的集合體
          import * as abc from './src/index.js';
    
          // 這是sum
          const sum = abc.sum;
    
          // 這是default
          const default = abc.default;
    


CommonJS

  • 導出(module.exports) & 引入

         const sum(a, b) => {
              return a + b;
          }
    
          const multiply = (a, b) => {
              return a * b;
          }
    
          module.exports = {
              sum,
              multiply
          }
    
          // 全部引入
          const utils = require('./src/index.js');
    
          // 部分引入
          const {sum, multiply} = require('./src/index.js');
    
  • 導出(exports)

          const sum(a, b) => {
              return a + b;
          }
          exports.sum = sum;
    
  • module.exports & exports
    這兩個東西一開始都是指向一個空物件,所以下面這樣能達到同樣的效果,是因為做的都是在那個空物件裡頭新增一個sum屬性,並賦值。

          module.export.sum = (a, b) => {
              return a + b;
          }
    
          exports.sum = (a, b) => {
              return a + b;
          }
    

    下面這樣exports會導出失敗,因為exports = ...,這個動作改變了exports的指向,它不再指向和module.exports同一個物件(那個最初的空物件)

          module.exports.hello = true; // Exported from require of module
          exports = { hello: false };  // Not exported, only available in the module
    

    exports shortcut
    module.exports與exports的差異

ESM引入,CommonJS導出

// 詳細看參考資料
object.defineproperty(exports, '__esmodule', { value: true })

node-fetch




Node.js環境

預設標準目前仍是CommonJS
v13.2.0開始Node.js可以穩定支援ES module
v8.5.0開始透過--experimental-modules flag 還是可以在v8.5.0環境用ES module

nodemon --experimental-modules index.mjs


.js & .cjs & .mjs & .es.js 的差異

  • .js:採取預設標準(CommonJS)
  • .cjs:走CommonJS標準
  • .mjs:走ESM標準
    node-fetch
  • .es.js:走ESM標準

將標準從CommonJS轉為ESM的方法

  • 副檔名用.mjs
  • 在package.json中將type設為module,這樣Node.js就會把package裡所有東西當ESM

          {
            "name": "my-library",
            "version": "1.0.0",
            "type": "module",
            // ...
          }
    


📖

CommonJS vs. ES modules in Node.js
__esModule 的作用
exports跟module.exports的差別 懶人包
關於ES6 模組系統


#ESM #CommonJS







Related Posts

實作 To do List SPA(上):前端部份

實作 To do List SPA(上):前端部份

跟你朋友介紹 Git

跟你朋友介紹 Git

教你朋友 CLI(command line)

教你朋友 CLI(command line)


Comments