模塊化概述——「模塊化」只是思想
最主流的代碼整合方式,安裝功能不同劃分不同模塊。
- 模塊化演變過程
- 模塊化規範
- 常用的模塊化打包工具
- 基於模塊化工具構建現代WEB應用
- 打包工具的優化技巧
模塊化的演進過程
Stage 1 - 文件劃分方式
完全依靠約定
├── index.html
├── module-01.js
└── module-02.js
- 通過scriptsrc屬性引入模塊
- 污染全局作用域,容易產生命名衝突
- 模塊成員可以隨意修改
- 無法管理模塊依賴關係
Stage 2 - 命名空間方式
依靠約定,模塊暴露全局對象, 所有成員都暴露在該對象下面,解決了污染全局作用域問題
var moduleA = {
name: 'module-a'
method1: function() {
console.log(this.name + 'method1')
}
method2: function() {
console.log(this.name + 'method2')
}
}
- 通過scriptsrc屬性引入模塊
- 模塊成員可以隨意修改
- 無法管理模塊依賴關係
Stage 3 - IIFE
立即執行函數方式,爲模塊提供私有空間。實現了私有成員的概念。通過自執行函數傳參的方式可以實現簡單的模塊化依賴處理
;
(function() {
var name = 'module-a'
function method1() {
console.log(name + 'method1')
}
function method2() {
console.log(name + 'method2')
}
window.moduleA = {
method1: method1,
method2: method2
}
})(jQuery)
- 通過scriptsrc屬性引入模塊
- 無法管理模塊依賴關係
模塊化規範的出現
模塊化標準+模塊化加載器
- 解決通過scriptsrc屬性引入模塊不受控制
- 解決無法管理模塊依賴關係
CommonJs規範
以同步的模式加載模塊,在node環境中不會存在問題,但是在瀏覽器環境會導致效率低下
- 一個文件就是一個模塊
- 每個模塊都有單獨的作用域
- 通過module.exports 導出成員
- 通過require函數載入模塊
AMD規範 + Require.js
異步模式加載模塊
- 使用相對複雜
- 模塊js文件請求頻繁
- 基本三方模塊都支持amd規範
define 定義模塊
// 參數1 模塊名字
// 參數2 聲明依賴項
// 參數3 callback函數 函數形參中接收定義依賴項
// 返回函數值爲導出模塊
define('module1', ['jquery', './module2'], function($, module2) {
return {
start: function() {
$('body').animate({
margin: '200px'
})
module2()
}
}
})
require 加載模塊
require(['./module2'], function(module1) {
module1.start()
})
模塊化標準規範——模塊化的最佳實踐
-
node
遵循CommonJs規範
-
web環境
遵循ES modules規範
ES modules
基本特性
- 自動採用嚴格模式,忽略 ‘use strict’
- 每個module 都運行在私用作用域當中
- 通過CORS方式請求外部JavaScript模塊,不支持文件訪問
- 標籤會延遲加載執行腳本
導入導出
直接導出
export const foo = 'es modules'
export function hello() {
console.log('hello')
}
export class Person {}
文件末尾導出
const foo = 'es modules'
function hello() {
console.log('hello')
}
class Person {}
export {
foo,
hello,
Person
}
別名導出
const foo = 'es modules'
export {
foo as myFoo
}
導出默認成員
const foo = 'es modules'
export default foo
常規引入
import {
foo,
hello,
Person
} from './module.js'
console.log(foo)
console.log(hello)
console.log(Person)
別名處理
import {
foo as myFoo
} from './module.js'
console.log(myFoo)
引入默認成員
import foo from './module.js'
導入導出注意事項
- 末尾導出非對象字面量導出, 而是固定的語法
- 導出的爲引用關係不是複製一個新的對象
- 模塊引入是並不是對象解構,而是固定的語法
- 模塊引入的模塊是隻讀的存在不能被修改
導入用法(原生)
- 不能省略文件後綴名
- 不能省略index
後續通過打包工具打包模塊時可以省略
- 不能省略 ./ 相對路徑,否則視爲三方依賴包
- 可以使用項目的絕對路徑
- 可以使用網絡資源
導出一個模塊裏的所有方法
import * as mod from './module.js'
console.log(mod)
- import 只能存在最頂層不能嵌套函數或if語句
- import 的 from 後面不能是變量
動態導入
import('./module.js').then(module => {
console.log(module)
})
默認成員與命名成員同時導入
import name, {
age
} from './module.js'
導出導入成員
// 常用於index 文件,做導出零散文件使用
export {
foo,
bar
}from './module.js'