1 ES Module 規範 ES Module 是目前使用較多的模塊化規範,在 Vue、React 中大量使用,大家應該非常熟悉。TypeScript 中的模塊化與 ES 類似。 1.1 導出模塊 導出模塊有兩種方式:按需導出 和 預設導出。 按需導出是使用 export 關鍵字,將需要導出的成員 ...
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.js 和 module2.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 打包
使用 npm 或 yarn 初始化項目:
yarn init -y
安裝 webpack、webpack-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, 控制台輸出如下:
3 ES Module 總結
導出模塊:
- 預設導出:export default xxx
- 按需導出 export const xxx
導入模塊:
-
預設導入: import xxx from 'xxx'
-
按需導入 import { xxx } from 'xxx'
4 JS 模塊化 4 大規範總結
前面優雅哥依次寫了模塊化的發展史,模塊化的規範(可進主頁查看每個規範詳細版本),現進行一個大彙總方便大家查閱和總結:
05 - ESM 規範
模塊化相關 demo 源碼可以 github 搜索關鍵詞 js-module-demo 或聯繫 程式員優雅哥 獲取。
源碼目錄如下:
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'
感謝你閱讀本文,如果本文給了你一點點幫助或者啟發,還請三連支持一下,點贊、關註、收藏,作者會持續與大家分享更多乾貨