一.模塊的分類(lèi)
A類(lèi):核心模塊 ,如http fs path等
B類(lèi):. or .. 開(kāi)頭的相對(duì)路徑文件模塊
C類(lèi):/開(kāi)頭的絕對(duì)路徑文件模塊
D類(lèi):非路徑形式的文件模塊跨细,如自定義的模塊
二.模塊的定位
優(yōu)先緩存
A類(lèi)模塊是node源碼編譯過(guò)程已經(jīng)編譯好的,加載最快,node啟動(dòng)時(shí)候會(huì)加載到緩存
B類(lèi)相對(duì)路徑的會(huì)在分析路徑的時(shí)候轉(zhuǎn)為真實(shí)路徑,將真實(shí)路徑作為索引铣减,編譯執(zhí)行后的結(jié)果放到緩存
C類(lèi)略
D類(lèi)從node_modules中進(jìn)行查找惕虑,這里我們寫(xiě)一個(gè)小demo看下查找路徑:
$ vim hello.js
輸入:
console.log("Hello World");
console.log(module.paths);
$ node hello.js
通過(guò)結(jié)果集可以看到查找路徑是逐級(jí)遞歸向上一直到根目錄
值得說(shuō)的是擴(kuò)展名:
建議最好require模塊的時(shí)候都帶上擴(kuò)展名,因?yàn)?node 會(huì)按照.js .json .node的次序補(bǔ)足擴(kuò)展名舞箍。
但是這個(gè)過(guò)程會(huì)調(diào)用fs模塊同步阻塞判斷文件是否存在,會(huì)引起性能問(wèn)題皆疹。因此引用非.js文件最好帶擴(kuò)展名疏橄。
目錄分析和包
node在當(dāng)前目錄下查找package.json 解析包描述對(duì)象,從中獲取main屬性指定的文件名進(jìn)行定位略就,如果沒(méi)找到會(huì)用index作為默認(rèn)文件名捎迫。
三.模塊的編譯
.js的編譯:fs模塊同步讀取文件后編譯執(zhí)行
.node:c/c++編寫(xiě)的,通過(guò)dlopen()加載執(zhí)行
.json:fs模塊同步讀取文件表牢,JSON.parse解析返回結(jié)果
其余擴(kuò)展名:被當(dāng)作js文件載入
js文件在編譯的時(shí)候窄绒,node會(huì)將文件內(nèi)容包裝到下面這個(gè)函數(shù)中:
(function (exports,require,module,__filename,__dirname){
//js模塊文件代碼.
});
因此,我們可以在模塊文件中使用這5個(gè)變量:
__filename:完整文件路徑
__dirname:文件目錄
exports:該屬性上的任何屬性和方法都可以被外部調(diào)用崔兴,但是模塊中其余的變量和屬性則不可以彰导。因?yàn)閑xports屬性是要被返回給調(diào)用方的蛔翅。
module:模塊對(duì)象自身
require:引用模塊
四.模塊調(diào)用棧
文件模塊就是我們上述一直提及的,開(kāi)發(fā)人員自己編寫(xiě)的模塊文件位谋,圖中分成 js模塊和c/c++擴(kuò)展模塊山析,其他只有一些場(chǎng)景需要提高性能等原因才會(huì)考慮采用,比如位運(yùn)算掏父。
核心模塊分為js核心模塊(我們上文指的核心模塊)和內(nèi)建模塊笋轨,我們程序一般不會(huì)直接調(diào)用內(nèi)建模塊,而是通過(guò)已經(jīng)用js核心模塊封裝的模塊赊淑。當(dāng)然也是有方法去直接調(diào)用的 process.binding('moduleName')
這邊的東西我說(shuō)的很少爵政,大家感興趣的可以看“深入淺出nodeJS 第二章”
五.包與npm
包和NPM是將模塊聯(lián)系起來(lái)的一種機(jī)制。
包實(shí)際上是一個(gè)存檔文件陶缺,即一個(gè)目錄直接打包為.zip 或者 tar.gz格式钾挟,安裝后解壓還原為目錄。符合CommonJS規(guī)范的包目錄應(yīng)該包含如下文件:
package.json:包描述文件
bin:可執(zhí)行二進(jìn)制文件目錄
lib:存放js代碼的目錄
doc:存放文檔的目錄
test:存放單元測(cè)試用例的代碼
NPM是Node包管理工具组哩,幫助完成第三方模塊的發(fā)布等龙,安裝,依賴(lài)等伶贰。npm的行為與package.json包描述文件有關(guān)蛛砰,npm世紀(jì)需要的package.json中定義的字段重要有:
----可以參考看這個(gè)帖子:[http://www.cnblogs.com/tzyy/p/5193811.html#_h1_2]
name:包名
version:版本號(hào),major.minor.revision格式
description:包簡(jiǎn)介
keywords:關(guān)鍵詞數(shù)組黍衙,npm用來(lái)做分類(lèi)搜索
repositories:托管源代碼的位置列表
author:包作者
bin:一些包作者希望包可以作為命令行工具使用泥畅,配置bin后,可以通過(guò)npm install package_name -g命令將腳本添加到執(zhí)行路徑中琅翻,可以命令行中直接執(zhí)行位仁。
main:模塊A使用require()引入包B時(shí),會(huì)優(yōu)先檢查包B的package.json中此字段方椎,并將其作為包中其余模塊的入口聂抢,如果查找失敗,會(huì)查找index關(guān)鍵詞棠众。
scripts:主要被包管理器用來(lái)安裝琳疏,編譯,測(cè)試和卸載包闸拿。
engines:支持的js引擎列表空盼,有效的引擎值包括 ejs,flusspferd,gpsee,jsc,spidermonkey,narwhal,node,v8
dependencies:使用當(dāng)前包需要依賴(lài)的包列表,npm會(huì)根據(jù)這個(gè)屬性幫助自動(dòng)加載依賴(lài)的包
devDependencies:一些模塊只在開(kāi)發(fā)時(shí)需要依賴(lài)新荤,配置這個(gè)屬性可以提示包的后續(xù)開(kāi)發(fā)者安裝依賴(lài)包揽趾。
NPM Demo(express框架的包文件)
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.3.4",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [{"name": "TJ Holowaychuk","email": "tj@vision-media.ca"},{"email": "aaron.heckmann+github@gmail.com"}{"name": "Ciaran Jessup","email": "ciaranj@gmail.com"},{"email":"rauchg@gmail.com"}],
"dependencies": {
"connect": "2.8.4",
"commander": "1.2.0",
"range-parser": "0.0.4",
"mkdirp": "0.3.5",
"cookie": "0.1.0",
"buffer-crc32": "0.2.1",
"fresh": "0.1.0",
"methods": "0.0.1",
"send": "0.1.3",
"cookie-signature": "1.0.1",
"debug": "*"
},
"devDependencies": {
"ejs": "*",
"mocha": "*",
"jade": "0.30.0",
"hjs": "*",
"stylus": "*",
"should": "*",
"connect-redis": "*",
"marked": "*",
"supertest": "0.6.0"
},
"keywords":["express","framework","sinatra","web","rest","restful", 2"router","app","api"],
"repository": "git://github.com/visionmedia/express",
"main": "index",
"bin": {"express": "./bin/express"},
"scripts": {
"prepublish": "npm prune",
"test": "make test"
},
"engines": {"node": "*"}
}
六.npm倉(cāng)庫(kù)
相對(duì)于命令行中執(zhí)行npm命令,NPM倉(cāng)庫(kù)是存放模塊的服務(wù)器苛骨。
Node在GitHub上托管源代碼篱瞎,在NPM上發(fā)布模塊苟呐,在代碼中使用第三方模塊包。
npm倉(cāng)庫(kù)設(shè)計(jì)基于CouchDB實(shí)現(xiàn)俐筋。
1.安裝erlang & CouchDB
因?yàn)閏ouchdb是基于erlang實(shí)現(xiàn)的掠抬,因此要先安裝erlang:
brew install erlang
erl #驗(yàn)證是否安裝成功
安裝CouchDB
brew install couchdb
couchdb & curl http://127.0.0.1:5984/ #查看是否安裝成功
#如果以前裝過(guò),在安裝之前要卸載
brew remove --force openssl erlang couchdb icu4c spidermonkey nspr
#瀏覽器查看數(shù)據(jù)庫(kù)
http://127.0.0.1:5984/_utils/
2.搭建NPM倉(cāng)庫(kù)
#調(diào)用couchDB接口創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)校哎,所有模塊將作為附件保存在這個(gè)數(shù)據(jù)庫(kù)中
#數(shù)據(jù)庫(kù)命名規(guī)則:Only lowercase characters (a-z), digits (0-9), and any of the characters _, $, (, ), +, -, and / are allowed
curl -X PUT http://127.0.0.1:5984/cat_registry
#刷新瀏覽器查看數(shù)據(jù)庫(kù)建立情況
#獲取npm倉(cāng)庫(kù)源代碼
mkdir npmware
git clone https://github.com/isaacs/npmjs.org.git
cd npmjs.org
--有個(gè)問(wèn)題,這個(gè)代碼倉(cāng)庫(kù)后續(xù)如何使用瞳步?
#安裝工具
#couchapp簡(jiǎn)介(百度百科)
#[CouchDB](http://baike.baidu.com/view/2024470.htm)
#CouchApp 是一個(gè)開(kāi)發(fā)使用的 Web 應(yīng)用的小型框架闷哆。它的主要功能是可以把一個(gè)文件系統(tǒng)的目錄轉(zhuǎn)換成 CouchDB 中的一個(gè)設(shè)計(jì)文檔。在開(kāi)發(fā)的時(shí)候单起,可以按照一般 Web 應(yīng)用的結(jié)構(gòu)來(lái)組織文件系統(tǒng)抱怔,當(dāng)需要測(cè)試和部署的時(shí)候,只需要一條命令就可以把該目錄保存到 CouchDB 中嘀倒。
npm install couchapp -g
#執(zhí)行如下語(yǔ)句會(huì)在當(dāng)前目錄下生成node_modules目錄屈留,然后安裝下面兩個(gè)模塊
npm install couchapp #在當(dāng)前代碼庫(kù)中安裝
npm install semver #版本檢查參考:https://docs.npmjs.com/misc/semver
#裝載NPM倉(cāng)庫(kù)代碼到CouchDB
couchapp push registry/app.js http://127.0.0.1:5984/cat_registry
#app.js會(huì)報(bào)錯(cuò),因?yàn)檫€沒(méi)搞清楚是為什么测蘑,我就將報(bào)錯(cuò)的部分注釋了灌危,然后能夠成功提交,圖1是報(bào)錯(cuò)碳胳,圖2是代碼注釋?zhuān)瑘D3是提交成功勇蝙。
訪(fǎng)問(wèn)查看上傳成功:http://127.0.0.1:5984/_utils/document.html?cat_registry/_design/scratch
七.局域npm庫(kù)的使用
npm install ** #默認(rèn)從全局npm倉(cāng)庫(kù)拉取
#從我們剛剛新建的局域庫(kù)拉取
npm install plusplus --registry=http://127.0.0.1:5984/cat_registry/_design/scratch/_rewrite
#這邊要插播一個(gè)修改couchdb的配置文件的地方,當(dāng)你訪(fǎng)問(wèn)下面的網(wǎng)址挨约,會(huì)返回“insecure_rewrite_rule too many ....”
http://127.0.0.1:5984/cat_registry/_design/scratch/_rewrite
ok,我們修改一下couchdb的配置文件味混,來(lái)解決這個(gè)問(wèn)題:
[參考:http://blog.csdn.net/nsrainbow/article/details/35989657/]
vim /usr/local/etc/couchdb/local.ini
新增:
[httpd]
secure_rewrites = false
bind_address=0.0.0.0
ps -ef | grep couchdb #第二列pid
kill -9 pid
couchapp #重啟
ok,下面來(lái)訪(fǎng)問(wèn)一下吧(127.0.0.1只能本機(jī)訪(fǎng)問(wèn)诫惭,換成0.0.0.0就可以被外部機(jī)器訪(fǎng)問(wèn)了):
http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite
上述的命令很長(zhǎng)翁锡,不容易記憶,這邊我們可以使用如下方式讓命令更簡(jiǎn)單一些
npm config set registry http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite
#修改~/.bashrc 新增一條匿名夕土,醬紫就可以區(qū)分官方倉(cāng)庫(kù)和本地倉(cāng)庫(kù)
alias lnpm = 'npm --registry=http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite'
八.上傳發(fā)布自己的npm包
#首先創(chuàng)建一個(gè)自己的github repo馆衔,訪(fǎng)問(wèn)網(wǎng)址進(jìn)行注冊(cè)
https://github.com
#注冊(cè)后,你會(huì)有一個(gè)自己的空庫(kù)隘弊,然后按照github提示的命令在本機(jī)進(jìn)行操作
git clone https://github.com/gongziLiu/lgz.git 9猓克隆一個(gè)倉(cāng)庫(kù)
cd lgz
touch README.md
git add README.md
git commit -m 'my first commit'
git push -u origin master
#創(chuàng)建新的分支用來(lái)存我們這次新建的npm包代碼,如圖
#新建分支
git branch myfirstnpm
#創(chuàng)建couchdb賬號(hào)
npm adduser --registry=http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite
#發(fā)布
npm publish --registry=http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite
但是我發(fā)現(xiàn)npm publish 并沒(méi)有幫我們git push 分支梨熙,所以還要我們自己手動(dòng)push上去开镣。
ok,下面驗(yàn)證一下在客戶(hù)端包的安裝
npm install testmynpmpublish --registry=http://0.0.0.0:5984/cat_registry/_design/scratch/_rewrite