這個倉庫記錄了一些關於javascript UMD
模塊規範的demo
,對我學習UMD
規範有了很大幫助,但願也能幫助到你。javascript
以前也寫了幾篇關於javascript
模塊的博客,連接以下:html
近幾天準備總結一下javascript
模塊的知識點,因此建了這個Git倉庫,若是能幫助到您,麻煩點個star
哦,很是感謝!java
這篇博客主要說下本身關於UMD
的一點認知和思考,從實現一個簡單的UMD
模塊,再到實現一個有依賴關係的UMD
模塊,整個過程加深了我對UMD
模塊的理解。node
所謂UMD (Universal Module Definition)
,就是一種javascript
通用模塊定義規範,讓你的模塊能在javascript
全部運行環境中發揮做用。git
實現一個UMD
模塊,就要考慮現有的主流javascript
模塊規範了,如CommonJS
, AMD
, CMD
等。那麼如何才能同時知足這幾種規範呢?github
首先要想到,模塊最終是要導出一個對象,函數,或者變量。shell
而不一樣的模塊規範,關於模塊導出這部分的定義是徹底不同的。編程
所以,咱們須要一種過渡機制。小程序
首先,咱們須要一個factory
,也就是工廠函數,它只負責返回你須要導出的內容(對象,函數,變量等)。hexo
咱們從導出一個簡單的對象開始。
function factory() { return { name: '我是一個umd模塊' } }
假設不考慮CommonJS
, AMD
, CMD
,僅僅將這個模塊做爲全局對象的一個屬性應該怎麼寫呢?
(function(root, factory) { console.log('沒有模塊環境,直接掛載在全局對象上') root.umdModule = factory(); }(this, function() { return { name: '我是一個umd模塊' } }))
咱們把factory
寫成一個匿名函數,利用IIFE
(當即執行函數)去執行工廠函數,返回的對象賦值給root.umdModule
,這裏的root
就是指向全局對象this
,其值多是window
或者global
,視運行環境而定。
打開效果頁面連接(要看源碼的話,點開Git倉庫),觀察Network
的文件加載順序,能夠看到,原則就是依賴先行。
要兼容AMD
也簡單,判斷一下環境,是否知足AMD
規範。若是知足,則使用require.js
提供的define
函數定義模塊。
(function(root, factory) { if (typeof define === 'function' && define.amd) { // 若是環境中有define函數,而且define函數具有amd屬性,則能夠判斷當前環境知足AMD規範 console.log('是AMD模塊規範,如require.js') define(factory) } else { console.log('沒有模塊環境,直接掛載在全局對象上') root.umdModule = factory(); } }(this, function() { return { name: '我是一個umd模塊' } }))
打開效果頁面連接,能夠看到,原則是調用者先加載,所依賴的模塊後加載。
同理,接着判斷當前環境是否知足CommonJS
或CMD
規範,分別使用相應的模塊定義方法進行模塊定義。
(function(root, factory) { if (typeof module === 'object' && typeof module.exports === 'object') { console.log('是commonjs模塊規範,nodejs環境') module.exports = factory(); } else if (typeof define === 'function' && define.amd) { console.log('是AMD模塊規範,如require.js') define(factory) } else if (typeof define === 'function' && define.cmd) { console.log('是CMD模塊規範,如sea.js') define(function(require, exports, module) { module.exports = factory() }) } else { console.log('沒有模塊環境,直接掛載在全局對象上') root.umdModule = factory(); } }(this, function() { return { name: '我是一個umd模塊' } }))
最終,使用require.js
, sea.js
, nodejs
或全局對象掛載屬性等方式都能完美地使用umd-module.js
這個模塊,實現了大一統。
給個sea.js
調用UMD
的效果頁面連接,sea.js調用UMD模塊
而nodejs
調用UMD
模塊須要執行node
命令,
node umd-simple-used-by-nodejs
效果以下:
固然,咱們不能止步於此,模塊會被調用,固然也會調用其餘模塊。所以咱們還須要實現一個有依賴關係的UMD
模塊,來驗證UMD
規範的可行性。
這個簡單,在html
中你的模塊前引入所依賴的模塊便可。umd-module-depended
和umd-module
都是UMD
模塊,後者依賴前者。
<!DOCTYPE html> <html> <head> <title>Test UMD</title> <!-- 依賴放前面 --> <script src="assets/js/umd-dep/umd-module-depended.js"></script> <script src="assets/js/umd-dep/umd-module.js"></script> <script src="assets/js/umd-dep/umd-global.js"></script> </head> <body> <h1>測試UMD模塊</h1> <h2></h2> <p id="content"></p> <p id="content2"></p> </body> </html>
點開效果頁面連接,看得更清楚明白!
咱們先在入口文件umd-main-requirejs.js
中,定義好模塊路徑,方便調用。
require.config({ baseUrl: "./assets/js/umd-dep/", paths: { umd: "umd-module", depModule: "umd-module-depended" } });
被依賴的模塊umd-module-depended
,只須要簡單實現UMD
規範便可。
而調用者umd-module
,則須要作一些處理。按照require.js
的規範來便可, define
時,指定依賴的模塊depModule
,而匿名工廠函數須要在參數上接收依賴的模塊depModule
。
(function(root, factory) { if (typeof define === 'function' && define.amd) { console.log('是AMD模塊規範,如require.js') define(['depModule'], factory) } else { console.log('沒有模塊環境,直接掛載在全局對象上') root.umdModule = factory(root.depModule); } }(this, function(depModule) { console.log('我調用了依賴模塊', depModule) // ...省略了一些代碼,去代碼倉庫看吧 return { name: '我本身是一個umd模塊' } }))
打開效果頁面連接,看得更清楚明白!
同理,各類規範要求你怎麼寫模塊依賴,你就怎麼寫就行。
(function(root, factory) { if (typeof module === 'object' && typeof module.exports === 'object') { console.log('是commonjs模塊規範,nodejs環境') var depModule = require('./umd-module-depended') module.exports = factory(depModule); } else if (typeof define === 'function' && define.amd) { console.log('是AMD模塊規範,如require.js') define(['depModule'], factory) } else if (typeof define === 'function' && define.cmd) { console.log('是CMD模塊規範,如sea.js') define(function(require, exports, module) { var depModule = require('depModule') module.exports = factory(depModule) }) } else { console.log('沒有模塊環境,直接掛載在全局對象上') root.umdModule = factory(root.depModule); } }(this, function(depModule) { console.log('我調用了依賴模塊', depModule) // ...省略了一些代碼,去代碼倉庫看吧 return { name: '我本身是一個umd模塊' } }))
給個sea.js
調用的示例連接。
而nodejs
調用也是經過命令行測試,
node umd-dep-used-by-nodejs
效果以下:
以上實現了簡單的UMD
模塊,也驗證了UMD
模塊間存在依賴關係時的可行性。雖然本文是以簡單對象導出爲例,但足以做爲咱們深刻UMD
規範的起點,加油!
最後厚着臉皮求個star
,點亮我吧
掃一掃下方小程序二維碼或搜索Tusi博客
,即刻閱讀最新文章!