本文的目的是爲了能大讓家更好的認識 Mod,之因此引入 RequireJS/SeaJS 的對比主要是應你們要求更清晰的對比應用場景,並非爲了比較出孰勝孰劣,RequireJS 和 SeaJS 都是模塊化漫漫之路的先驅者,向他們致敬!css
模塊化是一種處理複雜系統分解成爲更好的可管理模塊的方式,它能夠把系統代碼劃分爲一系列職責單一,高度解耦且可替換的模塊,採用模塊化可讓系統的可維護性更加簡單易得。html
JavaScript 並無爲開發者們提供以一種簡潔、有條理地的方式來管理模塊的方法。從出發點來看,Mod和 RequireJS/SeaJS 是一致的,爲開發者提供一套 JavaScript 模塊化開發方案,讓 JavaScript 的模塊化開發變得更簡單天然。可是在實現的過程當中卻存在巨大着的差別。前端
Mod嚴格上來說並非一個獨立的模塊化框架,它是被設計用作前端工程化模塊化方案的 JavaScript 支持,須要和自動化工具、後端框架配合來使用,目的在於但願給工程師提供一個相似 nodeJS 同樣的開發體驗,同時具有很好的線上性能。node
RequireJS 和 SeaJS 的定位主要是 Web 瀏覽器端的模塊加載器,依靠 JavaScript 運行時來支持模塊定義、依賴分析和加載等功能。jquery
RequireJS 遵照的是 AMD 規範,SeaJS 遵照的是 CMD 的規範。AMD/CMD 規範使用的是「異步模塊定義」的方式,這種方式給開發帶來了極大的不便,全部的同步代碼都須要修改成異步的方式,咱們是否能夠在前端開發中使用「 CommonJS 」的方式,開發者可使用天然、容易理解的模塊定義和調用方式,不須要關注模塊是否異步,不須要改變開發者的開發行爲。答案固然是確定的,Mod並不徹底遵照 AMD/CMD 規範,也正是爲了爲開發者提供更簡單天然的開發體驗。git
Mod 使用 define 來定義一個模塊:github
define (id, factory)
factory 提供了 3 個參數:require, exports, module ,用於模塊的引用和導出。json
在日常開發中,咱們無需關注模塊定義,工具會自動對 JS 進行 define 包裝處理:後端
JS 源碼前端工程化
//common/widget/menu/menu.js var $ = require('common:widget/jquery/jquery.js'); exports.init = function() { $('.menu-ui ul li a').click(function(event) { var self = this; $('.menu-ui ul li a.active').removeClass('active'); $(self).addClass('active'); event.preventDefault(); }); };
編譯後代碼
define('common:widget/menu/menu.js', function(require, exports, module){ var $ = require('common:widget/jquery/jquery.js'); exports.init = function() { $('.menu-ui ul li a').click(function(event) { var self = this; $('.menu-ui ul li a.active').removeClass('active'); $(self).addClass('active'); event.preventDefault(); }); }; });
Mod會在模塊初始化以前自動加載相關依賴。所以當咱們須要一個模塊時,只需提供一個模塊名便可獲取:
require (id)
由於所需的模塊都已預先加載,所以 require 能夠當即(同步)返回該模塊引用。不管在頁面的 script 仍是模塊內部,工程師均可以放心經過 require 來加載模塊,不須要考慮什麼時候該使用同步接口什麼時候調用異步接口。
RequireJS/SeaJS 經過過 JavaScript 運行時來支持「匿名閉包」、「依賴分析」和「模塊加載」等功能,「依賴分析」須要在 JavaScript 運行時經過正則匹配到模塊的依賴關係,而後順着依賴鏈(也就是順着模塊聲明的依賴層層進入,直到沒有依賴爲止)把全部須要加載的模塊按順序一一加載完畢, 當模塊不少、依賴關係複雜的狀況下會嚴重影響頁面性能。Mod經過如下設計避免瞭如上問題:
經過以上設計,Mod極其精簡,整個文件只有 100 多行,相比下 RequireJS 有 2000 多行,SeaJS 有將近 1000 行。
經過 RequireJS/SeaJS 進行模塊化開發後,合併靜態資源(打包)將變得十分不方便和晦澀難懂,每一個文件裏只能有一個模塊,不管是「 combo 插件」仍是「 flush 插件」,都須要咱們修改模塊化調用的代碼,這無疑是雪上加霜,工程師不只須要在開發的時候關注模塊定義,在調用的時候還須要關注在一個請求裏面加載哪些模 塊比較合適,模塊化的初衷是爲了提升開發效率、下降維護成本,但咱們發現這樣的模塊化方案實際上並無下降維護成本,某種程度上來講使得整個項目更加複雜 了。而使用 Mod,工程師只須要在配置文件配置合併策略便可,並不須要關注其餘細節,Mod會自動處理好依賴以及合併信息並在模塊初始化以前將模塊的靜態資源以及所依賴的模塊加載並準備好。
整個Mod模塊化流程以下:
經過自動化工具對模塊進行編譯處理,包括對對 JavaScript 模塊添加閉包、記錄每一個靜態資源的部署路徑以及依賴關係並生成資源表(resource map),以下所示,
{ "res": { "demo.js": { "uri": "/static/js/demo_33c5143.js", "type": "js", "deps": [ "demo.css" ], "pkg": "p0" }, "index.html": { "uri": "/index.html", "type": "html", "deps": [ "demo.js", "demo.css" ] }, "script.js": { "uri": "/static/js/script_32300bf.js", "type": "js", "pkg": "p0" } }, "pkg": { "p0": { "uri": "/static/pkg/aio_5bb04ef.js", "type": "js", "has": [ "demo.js", "script.js" ], "deps": [ "demo.css" ] } } }
全部被打包的資源會有一個 pkg 屬性 指向該表中的資源,而這個資源,正是咱們配置的打包策略。有了這些信息,咱們能夠經過 Mod 框架(Mod 和後端框架)來管理和控制模塊的加載。Mod的模塊化能夠十分靈活的適應各類性能優化場景,咱們還能夠經過監控模塊的調用狀況,自動生成最優的打包配置,讓網站能夠自適應優化。
Mod提供的是一體化的模塊化解決方案,更多的是從工程化、自動化的角度去考慮,RequireJS/SeaJS 更獨立靈活。
參考:http://fex.baidu.com/blog/2014/04/fis-modjs-requirejs-seajs/?utm_source=tuicool&utm_medium=referral
http://www.tuicool.com/articles/yuY36n