---
# System prepended metadata

title: 模組的匯出與匯入
tags: [web develop]

---

---
tags: web develop
---
# 模組的匯出與匯入

[TOC]

## What
- 模組是一種的功能封裝機制，可以優化專案的設計、可維護性、測試更輕鬆
- 模組以文件承載，模組內所有變數，外部無法訪問，需要匯出才可供外部使用
- 模組化，允許匯出與匯入模組
- 可以便於使用別人以npm開發的豐富模組生態系統
### CommonJS規範
  - 是Ndoe.js的模組化規範
  - 瀏覽器無法直接使用Common.js規範，需要依賴打包工具進行支持，如 Webpack 
### ES Module規範
  - ES Module ( ES6 Module / ECMAScript  Module/ JavaScript Module)
  - ES6 的新語法
  - JS的官方包裝機制，JS的正式規範，可以直接在瀏覽器執行
  - React屬於前端框架，使用ES Module
  - Node.js也支援

### JS的模組化發展過程：
- 無模組 ⇒ CJS ⇒ 社區實現 AMD、CMD、UND ⇒ ESM
- 社區實現了諸多規範：AMD、CMD、UND
  - AMD：與CommonJS規範，主要區別是異步加載模組
  - CMD：與AMD規範類似，主要區別是依賴後置，模組加載完後再執行(?)
  - UND：AMD規範與CommonJS規範的結合
在導入模組庫後，都能在瀏覽器直接執行，最終被整合成了ESM

## Why
- 隨著js的複雜度與能力提升，程式維護成本相應提高，產生兩個問題：
  - 命名空間衝突：所有腳本都暴露在全域作用域下，有命名衝突的風險，如，jquery和zepto都使用window.$
  - 依賴關係不清晰：對於腳本的依賴、版本、加載順序，無法合理管理
- 用模組匯入匯出，才能拆分成不同檔案，職責分離

## Which
- 前後端模組系統，語法不同
### 前端模組系統：ES Module  (ESM)
- 如前端框架 react.js
- [補充：ESM 在 React 中的使用建議](#補充：ESM-在-React-中的使用建議)

### 後端模組系統：CommonJS (CJS)
#### When(CJS)
- Node.js
- 原先不能使用 ESM，可用 CJS
- Node.js 12版本後(2019-04-23發佈)，支援 ESM
- Node.js 13版本後，可以更容易的使用 ESM 語法
使得 Node.js可以直接使用ESM，而不需要透過babel等編譯器

#### How(CJS)
Node >= v13，可選擇下面兩種其一：
- 將 ES modules 檔案的副檔名存為 .mjs
- 在 package.json 檔案中，加入 `{ “type”: “module” }`

參考：https://eddychang.me/node-es6-module

## How

### CJS
```javascript
// 後端 CommonJS => ES5
// 匯入
const products = require('./data/products')
// 匯出
exports products
module.exports = products
```

### ESM 
```javascript
// 預設 匯出/匯入
export default products;
import products from "../products"; 
// 實名 匯出/匯入
export products;
import { products } from "../products"; 
```
- 實名匯出，匯入匯出的變數名稱必須一致

#### 實名匯出：直接定義變數並匯出
```javascript
// 匯出 
// in demoA.js
export const fruit1 = "apple";
export const fruit2 = "banana";
// 匯入 
// in demoB.js
import { fruit1, fruit2, } from "./demoA";
console.log(fruit1); // apple
```
#### 實名匯出：先定義好變數再匯出
- 匯出匯入時，都可以透過as修改名稱
- export後面接的不是物件
```javascript
// 
// 匯出 
// in demoA.js
const fruit1 = "apple";
const fruit2 = "banana";
export {
 fruit1,
 fruit2 as fruit222,
}

// 匯入 
// in demoB.js
import {  
  fruit1 as fruit111,
  fruit222, 
} from "./demoA";
console.log(fruit111); // apple
```
### ESM 預設匯出
- 可以直接匯出，不用管匯出變數有哪些
- 匯入時可以隨意取名
- 一隻檔案只能有一個export default 
```javascript
// 匯出 
// in demoA.js
export default ["apple, "banana", "cherry"];
                
// 匯入 
// in demoB.js
import products from "./demoA"
```

### 補充：ESM 在 React 中的使用建議
React 開發時，檔名、元件名稱、匯出名稱都要一致
```javascript
function App(){
  return(
    <></>
  )
}
export default App;
```
有些開發者為求程式簡潔，會寫成 export function App() { }，即直接定義並匯出
```javascript
export function App(){
  return(
    <></>
  )
}
```
箭頭函式，就無法前面直接接 export
```javascript
const App = () => {
  return(
    <></>
  )
}
export default App;
```

