模塊化是將一個總體系統按特定規則劃分爲各個獨立的個體。好比計算機模塊化爲CPU、內存、電源、顯示器等等。模塊化是一個簡化複雜的過程,同時在模塊化後各個獨立的個體之間的協調處理將變得更加的重要。用來協調處理各個模塊之間的工做的部分稱之爲模塊管理,監管和調配各個模塊可以正常工做,並能處理意外錯誤。javascript
隨着模塊的數量增長,如何處理模塊顯得很是的重要,要保證各個模塊之間的工做不會過度耦合、不會致使模塊之間互相抵觸,還要保證好各個模塊之間的依賴關係。html
咱們熟悉的jquery插件就至關因而jquery的模塊化,這些模塊是掛載在系統主枝幹上的,也就是說命名了一個模塊a,那麼就不能再命名一個模塊a,不然的話會出現模塊覆蓋的問題。前端
爲了解決這種問題,一種隨時用隨時取的模塊思想誕生了,即便是在其餘語言中存在好久,如c#的useing等,以及常被人們津津樂道的class類。在js中,客戶端語言和服務器語言最大的區別就是,使用源代碼必須從服務器上下載下來,而後才能解釋運行。由於種種網絡緣由,並不能保證模塊可以正常的加載進來,如何加載模塊又能夠分紅兩類。java
在js業界,模塊的加載分爲AMD、CMD兩類,它們都有本身的適合場合,尤爲是在服務端和客戶端之間。node
AMD、CMD的使用場合沒有硬性規定,各取所需,合適的就是最好的。jquery
在模塊規範上,就有着本質的區別,所以模塊化的過程也是不一樣的。git
如:github
// AMD // 定義 module1 ,依賴 depend1 和 depend2 define("module1", [" depend1", "depend2"], function (depend1, depend2) { // depend1 // depend2 }); // 定義 module2 ,依賴 module1 define("module2", ["module1"], function (module1) { // module1 }); // CMD // 定義模塊爲文件名 define(function (require, exports, module) { // require // exports // module });
AMD和CMD的模塊定義很是的相似,都使用了define函數。不一樣的是,AMD模塊規範,在定義模塊的時候就既定了依賴模塊,而CMD模塊並未這麼作,模塊之間的依賴關係有額外的配置文件決定。npm
在前端JS框架中,遵循AMD的有requireJS,遵循CMD的有seajs,各具特點。json
nodejs中的模塊化遵循CMD,但又有些不一樣。
// 新建一個計算圓周長、圓面積的模塊 var pi = Math.PI; // 計算周長 exports.perimeter = function (r) { return 2 * pi * r; } // 計算面積 exports.area = function (r) { return pi * r * r; }
如上,定義了一個計算圓周長、圓面積的模塊,由於每個文件就是一個模塊,就不須要寫define函數了,直接寫出口exports便可。exports出口能夠是任何對象。如:
A、出口是字面量
// module.js // 模塊出口是字面量 module.exports="I'm a module!"; // index.js // 調用模塊 var md = require("./module.js"); md;
B、出口是對象
// module.js // 模塊出口是對象 module.exports={ name:"yundanran", love:"ming" }; // index.js // 調用模塊 var md = require("./module.js"); md.name; md.love;
C、出口是類
// module.js function Animal(type){ this.type=type; } Animal.prototype.say=function(){ return "Animal type is "+this.type; } // 出口是一個類 module.exports=Animal; // index.js // 模塊調用 var Md = require("./module.js"); var md = new Md("people"); md.say();
D、出口是函數
// module.js exports.fn1 = function () { return "fn1"; } exports.fn2 = function () { return "fn2"; } // index.js var md = require("./module.js"); md.fn1(); md.fn2();
由多個模塊文件組成的一個總體,稱之爲包(模塊包、package),這些模塊文件合做完成一個相對更大一點的功能,具備一些處理錯誤、異常的能力。在模塊包(文件夾)中約定包含:
新建一個包module1,用來計算圓柱體的面積和體積。新建文件、文件夾以下:
lib/circle.js:
// 計算圓周長、面積的模塊 var pi = Math.PI; module.exports = { perimeter: function (r) { return 2 * pi * r; }, area: function (r) { return pi * r * r; } };
lib/rect.js:
// 計算矩形面積模塊 module.exports = function (w, h) { return w * h; }
lib/index.js:
// 計算圓柱面積、體積 // 引用 circle 模塊 var circle = require("./circle.js"); // 引用 rect 模塊 var rect = require("./rect.js"); exports.area = function (r, h) { return 2 * circle.area(r) + circle.perimeter(r) * h; } exports.volume = function (r, h) { return circle.area(r) * h; }
index.js:
module.exports=require("./lib"); // 至關於 module.exports=require("./lib/index.js");
而後,cd到該模塊文件夾,執行如下命令(關於nmp後續再說):
npm init
命令板會要求輸入模塊包的各類信息,最後在該包文件夾下生成package.json文件(/node_modules/module1/package.json)。package.json文件包含了模塊包的各類信息,其中name值就是引用包須要用的名稱。例package.json:
{ "name": "module1", "version": "1.0.0", "description": "", "main": "index.js", "directories": { "doc": "doc", "test": "test" }, "scripts": { "test": "test" }, "author": "ydr.me", "license": "BSD-2-Clause" }
引用該模塊包,在/app3/index.js:
// 引用系統的 http 模塊 var http = require("http"); // 引用系統的 url 模塊 var url = require("url"); // 引用系統的 querystring 模塊 var qs = require("querystring"); // 引用自定義 module1 模塊,名稱即爲 package.json 裏的 name 值 var module1 = require("module1"); http.createServer(function (request, response) { var query=qs.parse(url.parse(request.url).query); var r = query.r; var h = query.h; if (r !== undefined && h !== undefined) { write(response, "<h1>計算圓柱的面積和體積</h1>\ <p>半徑 => " + r + "</p>\ <p>高 => " + r + "</p>\ <p>面積 => " + module1.area(r,h) + "</p>\ <p>體積 => " + module1.volume(r,h) + "</p>"); } else { write(response, "<h1>計算圓柱的面積和體積</h1>\ <p>請輸入圓柱的班級或高</p>"); } }).listen(2014); function write(response, text) { response.writeHead(200, { "content-type": "text/html" }); response.write(text); response.end(); }
打開localhost:2014便可看到效果。
A、直接使用模塊名稱
在nodejs中,引用一個模塊(包)名稱,遵循如下規範。如在/app3/index.js中引用test模塊包
var test = require("test");
系統依次搜尋如下路徑,直到找到爲止:
若是是引用如下系統的核心模塊也能夠直接使用模塊名稱:
B、標明模塊路徑
./
=> 當前路徑../
=> 上層路徑/
=> 根路徑如:
// 引用同級目錄的test.js var test = require("./test.js"); // 引用上級目錄的test.js var test = require("../test.js"); // 引用根級目錄的test.js var test = require("/test.js");
https://github.com/amdjs/amdjs-api/wiki/AMD
https://github.com/cmdjs/specification/blob/master/draft/module.md