JS 模組化- 05 ES Module & 4 大規範總結

2022-09-28 18:00:25

1 ES Module 規範

ES Module 是目前使用較多的模組化規範,在 Vue、React 中大量使用,大家應該非常熟悉。TypeScript 中的模組化與 ES 類似。

1.1 匯出模組

匯出模組有兩種方式:按需匯出預設匯出

按需匯出是使用 export 關鍵字,將需要匯出的成員(變數、函數、物件等)依次匯出:

export const xxx = ''
export const xxx = () => {}

一個模組中可以有多個按需匯出,但只能有一個預設匯出。假設預設匯出 A 模組,當 B 模組直接匯入模組 A 時,其匯入的值就是模組 A 預設匯出的值。

export default {}

1.2 匯入模組

匯入按需匯出的模組:

import { xxx } from 'xxx'

上面語法中,花括號 {} 中的內容必須與匯出的名稱一致。

如果按需匯出的成員較多,可以使用 as 一次性匯入:

import * as xxx from 'xxx'

匯入預設匯出的模組:

import xxx from 'xxx'

也可以直接匯入一個模組,並直接執行該模組的程式碼:

import 'xxxxx'

2 使用 Webpack 編譯 ES Module

2.1 初始化專案

建立 modules 目錄,裡面存放兩個模組 module1.jsmodule2.js。入口檔案與 modules 目錄同級,名為 index.js。檔案和目錄結構如下:

05_ESM/
  |- modules/
    |- module1.js
    |- module2.js
  |- index.js
  |- index.html

2.2 實現兩個模組

module1.js 使用按需匯出變數 str1 和函數 fun1,預設匯出 user 物件:

console.log('in module1')

export const str1 = 'hello module1'

export const fun1 = (msg) => {
  return `module1:${msg}`
}


const user = {
  name: 'zhangsan',
  age: 30
}

export default user

module2.js 使用預設匯出,匯出一個物件,這個物件包括屬性 str2 和方法 fun2

console.log('in module2')

const str2 = 'hello module2'

const fun2 = (msg) => {
  return `module2:${msg}`
}

export default {
  str2,
  fun2
}

2.3 實現入口檔案

在入口檔案 index.js 中匯入兩個模組。由於 module1.js 是按需匯出,故匯入時需要使用 {}module2.js 是預設匯出,故此處可以直接匯入:

import { str1, fun1 } from './modules/module1'
import m2 from './modules/module2'

console.log(str1)
console.log(fun1('程式設計師優雅哥'))
console.log(m2.str2)
console.log(m2.fun2('youyacoder'))

2.4 入口 HTML

建立 index.html 檔案,使用 script 標籤匯入 index.js

<script src="./index.js"></script>

在瀏覽器中存取 index.html 檔案,控制檯會提示如下錯誤:

Uncaught SyntaxError: Cannot use import statement outside a module (at index.js:1:1)

這是由於瀏覽器不認識 ESM 語法。可以使用 babel 將 ES6 語法編譯為 ES5 的語法,然後使用 browserify 進行打包;也可以使用 webpack 打包。此處我使用 webpack 5

2.5 使用 Webpack 打包

使用 npmyarn 初始化專案:

yarn init -y

安裝 webpackwebpack-cli 為開發依賴:

yarn add webpack webpack-cli -D 

使用 webpack 打包:

npx webpack ./index.js -o ./dist/ --mode development

上面的打包命令直接在命令中設定引數,省略了額外的設定的檔案。該命令指定了打包的入口檔案為:index.js;輸出的目錄為 dist 目錄,打包模式為 development。關於 webpack 5 的使用,有興趣的可以看優雅哥的 webpack 5 系列文章。

執行完打包命令後,會生成 dist 目錄,並且在該目錄中有個 main.js 檔案。

index.html 中刪除之前引入的 index.js,替換為 dist/main.js

<script src="./dist/main.js"></script>

重新在瀏覽器中存取 index.html, 控制檯輸出如下:

原始碼目錄如下:

js-module-demo/
|- 01_Histry/			模組化發展史
|- 02_CommonJS/		CommonJS 規範
|- 03_AMD/				ADM 規範
|- 04_CMD/				CMD 規範
|- 05_ESM/				ESM 規範

各個模組化規範有相似之處,也有差異,模組定義與模組載入的語法如下:

4.1 Common JS 規範

定義模組的語法:

// 暴露函數
module.exports = function () {}

// 暴露物件
module.exports = {
  xxx: () => {}
}

exports.xxx = {}

exports.xxx = function() {}

載入模組的語法:

const xxx = require('xxxx')

4.2 AMD 規範

定義模組的語法:

define(id?, dependencies?, factory)

載入模組的語法:

require([module], callback)

4.3 CMD 規範

定義模組的語法:

// 定義模組
define(function(require, exports, module) {
	
	// 使用 exports 匯出模組
	exports.xxx = xxx
	
	//也可以使用 return 匯出模組
	// return xxx
})

載入模組的語法:

// 同步載入模組
const m1 = require('../xxx')

// 非同步載入模組
require.async('../xxx', function (m2) {
})

4.4 ESM 規範

匯出模組:

// 按需匯出
export const xxx = ''
export const xxx = () => {}

// 預設匯出
export default xxx

匯入模組:

import { xxx, yyy } from 'xxx'
import * as xxx from 'xxx'
import xxx from 'xxx'
import 'xxx'

感謝你閱讀本文,如果本文給了你一點點幫助或者啟發,還請三連支援一下,點贊、關注、收藏,作者會持續與大家分享更多幹貨