模組化開發 -ES Module&&CMD&&AMD
阿新 • • 發佈:2020-12-23
技術標籤:模組化javascriptmodule
概述
- 主流的前端開發正規化之一
- 主流的程式碼組織方式,劃分模組,單獨維護,降低成本
模組化規範
模組化標準 + 模組化載入器
CommonJS規範 node提出的一種約定
- 一個檔案是一個模組
- 每個模組都有單獨的作用域
- 通過module.exports匯出成員
- 通過require函式載入模組
CommonJS是以同步模式載入模組,瀏覽器端支援不好
AMD(Asynchronous Module Definition) 非同步的模組定義規範
Require.js 實現了AMD規範,是一種模組載入器
// 定義一個模組
define('module1', ['jquery','./module2'],function($,module2){
return {
start:function(){
$("body").animate({margin: '200px'})
module2()
}
}
})
// 載入一個模組
require(['./module1'],function(module1){
module1.start()
})
大多數第三方庫都支援AMD規範
- AMD使用相對複雜
- 模組JS檔案請求頻繁
Sea.js + CMD 淘寶推出的,後來被AMD相容
// CMD 規範 (類似CommonJS規範)
define(function(require,exports,module){
// 通過 require 引入依賴
var $ = require('jquery')
// 通過exports 或者module.exports對外暴露成員
module.exports = function(){
console.log('module 2 ~')
$('body').append('<p>module2</p>')
}
})
模組化標準實現規範
NodeJS 中一般 CommonJS
瀏覽器一般 ES Modules規範
commonJS是NodeJS中內建模組,直接使用匯出就可以
ES Module 是ES2015 新增,開始相容問題很多,是在語言層面實現模組化,隨著webpack等打包工具,成為最廣泛的模組標準
ES Module
基本特性
ES中採用嚴格模式,忽略 ‘use strict’
每個ES Module 都是執行在單獨的私有作用域
ESM 是通過Cors 的方式請求JS模組的
ESM 的script 標籤會延遲執行指令碼 相當於添加了difine屬性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ESModule.html</title>
</head>
<body>
<!-- 通過script 新增type = module 的屬性,可以實現ES Module的標準執行其中JS程式碼 -->
<script type="module">
console.log('module1')
</script>
<!-- 1. ES中採用嚴格模式,忽略 'use strict' -->
<script type="module">
console.log(this)
</script>
<!-- 2. 每個ES Module 都是執行在單獨的作用域 -->
<script type="module">
console.log(this)
var foo = 100;
</script>
<script type="module">
console.log(foo) //訪問不到,沒有全域性變數汙染
</script>
<!-- 3. ESM 是通過Cors 的方式請求JS模組的 -->
<script type="module" src="https://libs.baidu.com/hquery/2.0.0/jquery.min.js"></script>
<!-- 4. ESM 的script 標籤會延遲執行指令碼 相當於添加了difine屬性 -->
<script>
// script 不新增module 會阻塞程式碼執行
// 新增之後會先載入程式碼再執行JS模組
</script>
</body>
</html>
ES Module匯出
利用export關鍵詞
export var name = 'foo module'
import {name} from './module.js'
// 匯出多個
var names = 'names';
function hello(){
console.log('hello')
}
class Person{}
export {name,hello,Person}
//匯出從命名
export {
name as fooName
}
import {fooName} from './module.js'
// defalut 關鍵詞
export {
name as default // 預設匯出成員
}
import {default as fooName} from './module.js' // 引入時候需要從命名
export default name // 會將 name 作為當前模組的預設匯出
import fooName from './module.js' // 直接接受模組匯出的預設成員,可隨意取名fooName
注意項
var name = 'kack'
var age = 18
var obj = {name,age}
export {name,age} //匯出的不是字面量物件,引入時候不是物件結構,匯出的是對應的引用關係
// 如果匯出物件,需要使用 export default ,之後可跟物件或者變數
export default {name,age}
import 的用法
import {name} from './module.js'
// from 後跟的必須是完整的路徑,不能節省副檔名
console.log(name)
// 打包工商使用時才可省略副檔名
// ./ 路徑不可省略
// 或者完整的路徑
import {names} from 'http://loaclhost:3000/import.js'
// 只執行而不是提取某個成員,{}可為空
import {} from './module'
// 獲取所有的匯出成員 ,通過as 放在特殊成員之中
import * as obj from './require'
console.log(obj)
// import 只能出現在頂層,不能被包裹在作用域內
if(true){
import {name} from './require' //錯誤
}
// 只能通過匯入函式方式,動態載入模組
import('./require') // 返回一個promise
.then(res=>console.log(res))
// 匯入default需要重新命名
import {name ,age, default as newName} from './require'
// 或者
import newName,{name ,age} from './require'
匯出匯入成員
例如專案中多個元件,可以新建一個公共部分接受所有成員,匯出
使用時節省匯出
import {Button, Avatar} from './components.js'
瀏覽器環境 Polyfill
Polyfill相容方案
是一個ES Module 的loader
npm install browser-es-module-loader
引入網頁中
<script src="dist/babel-browser-build.js"></script>
<script src="dist/browser-es-module-loader.js"></script>
ES Module in Node.js 支援情況
node版本>8.5
node環境可以直接原生方式實現
ES Module CommonJS
common.js
CommonJS 只能匯出一個預設成員
module.exports = {foo:'commonjs'}
exports.foo = 'commonjs'
//node原生 commonJS 不允許通過require 方式載入 ES Module
module.js
ES Module 中可以匯入 CommonJS 模組
import mod from './common.js'
console.log(mod) //可以
不能直接提取成員,import不是對匯出成員的結構
import {mod} from './common.js'
console.log(mod) //失敗
- ES Module 中可以匯入 CommonJS模組
- CommonJS 中不能匯入 ES Module
- CommonJS 始終只會匯出一個預設成員
- 注意import不是結構匯出物件