Web前端模塊化方法

前端模塊化

1. 模塊化優勢

目前因爲MVVM模式的流行,各類語言都更注重模塊化。模塊化設計的好處:前端

  1. 做用域:避免全局變量污染;
  2. 複用:可重複利用封裝的模塊爲不一樣地方實現相同功能;
  3. 解耦:減小不一樣功能代碼相互關聯性,讓代碼分工明確,也方便Debug;
  4. 按需加載:加快加載速度、異步加載沒必要要的部分;

2. 模塊化方法整理

從最先的script標籤開始,前端模塊化通過了多種編程方案的演化,逐步完善。vue

2.1 script標籤

<script src="module_a.js"></script>
<script src="module_b.js"></script>
<script src="main.js"></script>

全部的js文件共享全局做用域,容易引發做用域污染。webpack

2.2 閉包函數(當即執行函數)

(function(){
    // xxx
})()

這是筆者早年使用最多的js編程方式 0_0web

雖然避免了做用域污染的問題,但多個文件內的函數互相調用時,處理較爲麻煩。經常使用方法是:vue-router

  1. 在閉包內定義一個 window.myFunc = function(){} 的方法,在閉包外能夠調用;
  2. 使用事件監聽,給須要外部調用的方法設置事件,從外部觸發事件;介紹一種自定義事件來控制閉包函數間傳值的方法:
// 利用閉包函數自定義一個事件監聽觸發機制
// 自定義機制,不會受到默認的事件影響
var EventManager = (function() {
    var events = {}
    return {
        add: function(name, fn) {
            if(!events[name]){
                events[name] = [];
            }
            events[name].push(fn);
        },
        fire: function(name, args) {
            var fnList = events[name];
            if(fnList){
                for (var i = 0, l = fnList.length; i < l; i++) {
                    var fn = fnList[i];
                    if (fn && typeof fn == 'function') {
                        fn(args);
                    }
                }
            }
        }
    }
})()   

// 在閉包內監聽,可調用閉包內方法
(function() {
    EventManager.add('user.login', function(data) {
        console.log('user.login', data)
    })
})()

// 在任意位置觸發
EventManager.fire('user.login', {name: 'lc'})

自定義事件監聽,相對於window下的函數,更加靈活,也更符合模塊化的思想。舉個例子:
通訊系統中,用戶登陸後,須要獲取聊天記錄、通訊錄、我的信息,這些分別在不一樣的模塊(閉包)中。
若是用函數的思想,須要在登陸的地方進行不一樣的方法調用,這樣就使得登陸模塊與多個業務模塊產生了耦合;若是用自定義事件的方法,登陸後只須要廣播一個事件,同時在多個業務模塊分別監聽事件,各模塊間就徹底沒有耦合,就算任意刪掉一個模塊也能夠保證其餘模塊正常運行。編程

存在問題:閉包

不管是全局函數、全局事件、自定義事件,在調用每一個閉包中的方法時,鬥須要確保該閉包先執行後調用。在複雜項目中,須要先執行大量閉包函數,會致使啓動慢、邏輯複雜等各類問題。框架

2.3 AMD - 異步模塊定義

define('myfunc', ['math'], function(math) {
    math.sum(1, 2)
});

經過 define函數引入須要的依賴包,每一個模塊所依賴的包/模塊一目瞭然。less

2.4 CMD - 通用模塊定義

define(function(require, exports, module) {
    const math = require('math')
    math.sum(1, 2)
})

CMD的原則是將引入模塊儘可能後置,在使用的時候纔去引入。
這樣使得js執行時效率更高,更符合lazy load的思惟方式,但對代碼管理確不是很方便。異步

2.5. CommonJS

const math = require('math')

module.exports = function() {
    math.sum(1, 2)
}

目前NodeJS的模塊管理經常使用的就是這種方式,不少NPM的包也是這樣處理的模塊引入。

2.6 ES6的模塊化

import { myFunc1, myFunc2 } from 'myFuncs';
import Vue from 'vue';

export function hello() {};
export default {
  // ...
};

Vue、React等經常使用框架目前都在使用這種模塊化方法。

好比在vue中,配合vue-router,在組件中按需import模塊或模塊中的函數,能夠經過webpack實現按需加載。同時,這種模塊化方式使得模塊間的方法調用更加方便,不須要考慮模塊聲明先後順序,由於webpack會自動生成依賴樹。

2.7 樣式文件模塊化

// util.less
.common {
    color: pink;
}

// main.less
@import 'util.less'
.red {
    color: red;
}

樣式文件目前也支持模塊化。


參考:《深刻淺出Webpack》

相關文章
相關標籤/搜索