摘要:若不存在則模塊標識應(yīng)該默認定義為在加載器中被請求腳本的標識。其中是一個數(shù)組,里面的成員就是要加載的模塊是模塊加載完成之后的回調(diào)函數(shù)。在加載與兩個模塊之后執(zhí)行回調(diào)函數(shù)實現(xiàn)具體過程。在判斷是否支持是否存在,存在則使用方式加載模塊。
我的github(PS:希望star): https://github.com/tonyzheng1...
今天由于項目中引入的echarts的文件太大,requirejs經(jīng)常加載超時,不得不分開來加載echarts的各個圖表。但是使用echarts自帶的在線構(gòu)建工具生成的支持AMD 標準的模塊報錯,所以不得不使用echarts的全局函數(shù),使用requirejs的shim進行加載。借此機會學習一下AMD, CMD, CommonJS和UMD各自的規(guī)范,和它們之間的區(qū)別。
Javascript模塊化在了解這些規(guī)范之前,還是先了解一下什么是模塊化。
模塊化是指在解決某一個復雜問題或者一系列的雜糅問題時,依照一種分類的思維把問題進行系統(tǒng)性的分解以之處理。模塊化是一種處理復雜系統(tǒng)分解為代碼結(jié)構(gòu)更合理,可維護性更高的可管理的模塊的方式??梢韵胂笠粋€巨大的系統(tǒng)代碼,被整合優(yōu)化分割成邏輯性很強的模塊時,對于軟件是一種何等意義的存在。對于軟件行業(yè)來說:解耦軟件系統(tǒng)的復雜性,使得不管多么大的系統(tǒng),也可以將管理,開發(fā),維護變得“有理可循”。
還有一些對于模塊化一些專業(yè)的定義為:模塊化是軟件系統(tǒng)的屬性,這個系統(tǒng)被分解為一組高內(nèi)聚,低耦合的模塊。那么在理想狀態(tài)下我們只需要完成自己部分的核心業(yè)務(wù)邏輯代碼,其他方面的依賴可以通過直接加載被人已經(jīng)寫好模塊進行使用即可。
首先,既然是模塊化設(shè)計,那么作為一個模塊化系統(tǒng)所必須的能力:
定義封裝的模塊。
定義新模塊對其他模塊的依賴。
可對其他模塊的引入支持。
好了,思想有了,那么總要有點什么來建立一個模塊化的規(guī)范制度吧,不然各式各樣的模塊加載方式只會將局攪得更為混亂。那么在JavaScript中出現(xiàn)了一些非傳統(tǒng)模塊開發(fā)方式的規(guī)范 CommonJS的模塊規(guī)范,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。
CommonJSCommonJS是服務(wù)器端模塊的規(guī)范,Node.js采用了這個規(guī)范。
根據(jù)CommonJS規(guī)范,一個多帶帶的文件就是一個模塊。加載模塊使用require方法,該方法讀取一個文件并執(zhí)行,最后返回文件內(nèi)部的exports對象。
例如:
// foobar.js //私有變量 var test = 123; //公有方法 function foobar () { this.foo = function () { // do someing ... } this.bar = function () { //do someing ... } } //exports對象上的方法和變量是公有的 var foobar = new foobar(); exports.foobar = foobar;
//require方法默認讀取js文件,所以可以省略js后綴 var test = require("./boobar").foobar; test.bar();
CommonJS 加載模塊是同步的,所以只有加載完成才能執(zhí)行后面的操作。像Node.js主要用于服務(wù)器的編程,加載的模塊文件一般都已經(jīng)存在本地硬盤,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規(guī)范比較適用。但如果是瀏覽器環(huán)境,要從服務(wù)器加載模塊,這是就必須采用異步模式。所以就有了 AMD CMD 解決方案。
AMD和RequireJS AMDAMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義".
AMD設(shè)計出一個簡潔的寫模塊API:
define(id?, dependencies?, factory);
第一個參數(shù) id 為字符串類型,表示了模塊標識,為可選參數(shù)。若不存在則模塊標識應(yīng)該默認定義為在加載器中被請求腳本的標識。如果存在,那么模塊標識必須為頂層的或者一個絕對的標識。
第二個參數(shù),dependencies ,是一個當前模塊依賴的,已被模塊定義的模塊標識的數(shù)組字面量。
第三個參數(shù),factory,是一個需要進行實例化的函數(shù)或者一個對象。
通過參數(shù)的排列組合,這個簡單的API可以從容應(yīng)對各種各樣的應(yīng)用場景,如下所述。
定義無依賴的模塊
define( { add : function( x, y ){ return x + y ; } } );
定義有依賴的模塊
define(["alpha"], function( alpha ){ return { verb : function(){ return alpha.verb() + 1 ; } } });
定義數(shù)據(jù)對象模塊
define({ users: [], members: [] });
具名模塊
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){ export.verb = function(){ return beta.verb(); // or: return require("beta").verb(); } });
包裝模塊
define(function(require, exports, module) { var a = require("a"), b = require("b"); exports.action = function() {}; } );
不考慮多了一層函數(shù)外,格式和Node.js是一樣的:使用require獲取依賴模塊,使用exports導出API。
除了define外,AMD還保留一個關(guān)鍵字require。require 作為規(guī)范保留的全局標識符,可以實現(xiàn)為 module loader,也可以不實現(xiàn)。
模塊加載require([module], callback)
AMD模塊化規(guī)范中使用全局或局部的require函數(shù)實現(xiàn)加載一個或多個模塊,所有模塊加載完成之后的回調(diào)函數(shù)。
其中:
[module]:是一個數(shù)組,里面的成員就是要加載的模塊;
callback:是模塊加載完成之后的回調(diào)函數(shù)。
例如:加載一個math模塊,然后調(diào)用方法 math.add(2, 3);
require(["math"], function(math) { math.add(2, 3); });RequireJS
RequireJS 是一個前端的模塊化管理的工具庫,遵循AMD規(guī)范,它的作者就是AMD規(guī)范的創(chuàng)始人 James Burke。所以說RequireJS是對AMD規(guī)范的闡述一點也不為過。
RequireJS 的基本思想為:通過一個函數(shù)來將所有所需要的或者說所依賴的模塊實現(xiàn)裝載進來,然后返回一個新的函數(shù)(模塊),我們所有的關(guān)于新模塊的業(yè)務(wù)代碼都在這個函數(shù)內(nèi)部操作,其內(nèi)部也可無限制的使用已經(jīng)加載進來的以來的模塊。
那么scripts下的main.js則是指定的主代碼腳本文件,所有的依賴模塊代碼文件都將從該文件開始異步加載進入執(zhí)行。
define用于定義模塊,RequireJS要求每個模塊均放在獨立的文件之中。按照是否有依賴其他模塊的情況分為獨立模塊和非獨立模塊。
獨立模塊,不依賴其他模塊。直接定義:
define({ method1: function(){}, method2: function(){} });
也等價于
define(function() { return { method1: function(){}, method2: function(){} } });
非獨立模塊,對其他模塊有依賴。
define([ "module1", "module2" ], function(m1, m2) { ... });
或者:
define(function(require) { var m1 = require("module1"), m2 = require("module2"); ... });
簡單看了一下RequireJS的實現(xiàn)方式,其 require 實現(xiàn)只不過是提取 require 之后的模塊名,將其放入依賴關(guān)系之中。
require方法調(diào)用模塊
在require進行調(diào)用模塊時,其參數(shù)與define類似。
require(["foo", "bar"], function(foo, bar) { foo.func(); bar.func(); } );
在加載 foo 與 bar 兩個模塊之后執(zhí)行回調(diào)函數(shù)實現(xiàn)具體過程。
當然還可以如之前的例子中的,在define定義模塊內(nèi)部進行require調(diào)用模塊
define(function(require) { var m1 = require( "module1" ), m2 = require( "module2" ); ... });
define 和 require 這兩個定義模塊,調(diào)用模塊的方法合稱為AMD模式,定義模塊清晰,不會污染全局變量,清楚的顯示依賴關(guān)系。AMD模式可以用于瀏覽器環(huán)境并且允許非同步加載模塊,也可以按需動態(tài)加載模塊。
官網(wǎng) (http://www.requirejs.org/)
API (http://www.requirejs.org/docs...
CMD是SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出
對于依賴的模塊AMD是提前執(zhí)行,CMD是延遲執(zhí)行。不過RequireJS從2.0開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不通過)。
CMD推崇依賴就近,AMD推崇依賴前置。
//AMD define(["./a","./b"], function (a, b) { //依賴一開始就寫好 a.test(); b.test(); }); //CMD define(function (requie, exports, module) { //依賴可以就近書寫 var a = require("./a"); a.test(); ... //軟依賴 if (status) { var b = requie("./b"); b.test(); } });
雖然 AMD也支持CMD寫法,但依賴前置是官方文檔的默認模塊定義寫法。
AMD的API默認是一個當多個用,CMD嚴格的區(qū)分推崇職責單一。例如:AMD里require分全局的和局部的。CMD里面沒有全局的 require,提供 seajs.use()來實現(xiàn)模塊系統(tǒng)的加載啟動。CMD里每個API都簡單純粹。
UMDUMD是AMD和CommonJS的糅合
AMD模塊以瀏覽器第一的原則發(fā)展,異步加載模塊。
CommonJS模塊以服務(wù)器第一原則發(fā)展,選擇同步加載,它的模塊無需包裝(unwrapped modules)。
這迫使人們又想出另一個更通用的模式UMD (Universal Module Definition)。希望解決跨平臺的解決方案。
UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式。
在判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。
(function (window, factory) { if (typeof exports === "object") { module.exports = factory(); } else if (typeof define === "function" && define.amd) { define(factory); } else { window.eventUtil = factory(); } })(this, function () { //module ... });
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79112.html
摘要:函數(shù)有兩個參數(shù),第一個參數(shù)是當前運行時環(huán)境,第二個參數(shù)是模塊的定義體。在執(zhí)行規(guī)范時,會優(yōu)先判斷是當前環(huán)境是否支持環(huán)境,然后再檢驗是否支持環(huán)境,否則認為當前環(huán)境為瀏覽器環(huán)境 CommonJS規(guī)范 CommonJS定義的模塊分為3部分: require 模塊引用 exports 模塊導出 module 模塊本身 根據(jù)CommonJS規(guī)范,一個單獨的文件就是一個模塊。每一個模塊都是一個...
摘要:若不存在則模塊標識應(yīng)該默認定義為在加載器中被請求腳本的標識。這也是目前很多插件頭部的寫法,就是用來兼容各種不同模塊化的寫法。語句輸出的值是動態(tài)綁定的,綁定其所在的模塊。 前言 歷史上,js沒有模塊化的概念,不能把一個大工程分解成很多小模塊。這對于多人開發(fā)大型,復雜的項目形成了巨大的障礙,明顯降低了開發(fā)效率,java,Python有import,甚至連css都有@import,但是令人費...
摘要:常見模塊化方案是由社區(qū)提出的模塊化方案中的一種,遵循了這套方案。是模塊化規(guī)范中的一種,遵循了這套規(guī)范。中的模塊化能力由兩個命令構(gòu)成和,命令用于規(guī)定模塊的對外接口,命令用于輸入其他模塊提供的功能。 為什么需要模塊化 在ES6出現(xiàn)之前,JS語言本身并沒有提供模塊化能力,這為開發(fā)帶來了一些問題,其中最重要的兩個問題應(yīng)當是全局污染和依賴管理混亂。 // file a.js var name =...
摘要:要想讓模塊再次運行,必須清除緩存。模塊加載會阻塞接下來代碼的執(zhí)行,需要等到模塊加載完成才能繼續(xù)執(zhí)行同步加載。環(huán)境服務(wù)器環(huán)境應(yīng)用的模塊規(guī)范是參照實現(xiàn)的。這等同在每個模塊頭部,有一行這樣的命令。 commonJS 特點: 1、模塊可以多次加載,但是只會在第一次加載時運行一次,然后運行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運行,必須清除緩存。2、模塊加載會阻塞接下來代...
摘要:即盡早地執(zhí)行依賴模塊。阮一峰輸出值的引用模塊是動態(tài)關(guān)聯(lián)模塊中的值,輸出的是值得引用。的加載實現(xiàn)阮一峰運行時加載靜態(tài)編譯模塊是運行時加載,模塊是編譯時輸出接口。 模塊化開發(fā) 優(yōu)點 模塊化開發(fā)中,通常一個文件就是一個模塊,有自己的作用域,只向外暴露特定的變量和函數(shù),并且可以按需加載。 依賴自動加載,按需加載。 提高代碼復用率,方便進行代碼的管理,使得代碼管理更加清晰、規(guī)范。 減少了命名沖...
閱讀 1297·2021-09-27 13:35
閱讀 2605·2021-09-06 15:12
閱讀 3410·2019-08-30 15:55
閱讀 2863·2019-08-30 15:43
閱讀 454·2019-08-29 16:42
閱讀 3470·2019-08-29 15:39
閱讀 3093·2019-08-29 12:28
閱讀 1267·2019-08-29 11:11