nodejs的require的用法

require最常用的方法

require('http') 內置模塊

require('./server')  “./”表示當前路徑,後面跟的是相對路徑

require("../lib/server") ../表示上一級目錄,後面跟的也是相對路徑

server.js

var http = require('http'); 
function start(){ 
    server = http.createServer(function (req, res) {   
          res.writeHeader(200, {"Content-Type": "text/plain"});   
          res.end("Hello oschina\n");   
    })   
    server.listen(8000);   
    console.log("httpd start @8000");   

exports.start = start;   
index.js

//路徑根據自己的實際情況而定  
var server = require("./learnNode/server"); 
server.start(); 
下面介紹require

模塊
Node 使用 CommonJS 模塊系統。

Node 有一個簡單的模塊加載系統。在 Node 中,文件和模塊一一對應。比如,在 foo.js 加載同一目錄中的 circle.js 模塊。

foo.js 的內容:

var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
           + circle.area(4));circle.js 的內容:

var PI = Math.PI;

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};模塊 circle.js 導出了 area() 函數和 circumference() 函數,這樣它們就能從模塊外部訪問了。要導出對象,將其添加到特殊的 exports 對象就行。

模塊的局部變量是私有的。在本例中,變量 PI 是 circle.js 私有的。

核心模塊
Node 有一些已編譯成二進制的模塊,這些模塊將在本文檔的其他地方詳細​​介紹。

核心模塊在 Node 源代碼的 lib/ 文件夾中定義。

使用 require() 時,核心模塊總是優先加載。例如,require('http') 總是返回內置的 HTTP 模塊,即使該名稱的文件存在。

文件模塊
如果沒有找到確切的文件,Node 將嘗試給所需的文件名​​添加 .js 後綴再加載,然後再嘗試 .node。

.js 文件被視爲 JavaScript 文本文件,而 .node 文件被視爲已編譯的插件模塊,用 dlopen 加載。

模塊以 '/' 開頭表示使用文件的絕對路徑。例如,require('/home/marco/foo.js') 將加載 /home/marco/foo.js 文件。

模塊以 './' 開頭表示調用 require() 時使用相對路徑。也就是說,爲了保證 require('./circle') 能找到,circle.js 必須和 foo.js 在同一目錄。

如果不以 '/' 或'./' 開頭,該模塊可以是一個“核心模塊”,也可是一個從 node_modules 文件夾中加載的模塊。

從 `node_modules` 文件夾中加載
如果傳遞給 require() 有模塊標識符是不是原生模塊,而且不以 '/'、'../' 或'./' 開頭,那麼 Node 從當前模塊的父目錄+/node_modules 這個位置嘗試加載。

如果還是沒有找到,那麼它跳到上層目錄並依此類推,直到找到模塊,或者達到根目錄爲止。

例如,如果在文件 '/home/ry/projects/foo.js' 中調用 require('bar.js'),那麼 Node 將在下列位置查找,順序如下:

/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
這就允許程序將依賴關係本地化,防止它們衝突。

優化 `node_modules` 查找過程
當嵌套依賴關係的層次很深時,這個文件查找列表可能會變得很長。因此,在查找時進行如下優化:

首先,/node_modules 不會附加到一個以 /node_modules 結尾的文件夾後面。

其次,如果調用 require() 的文件已經在一個 node_modules 層級裏,那麼最頂層的 node_modules 文件夾將被視爲搜索樹的根。

例如,如果在文件 '/home/ry/projects/foo/node_modules/bar/node_modules/baz/quux.js' 中調用 require('asdf.js'),那麼 Node 將搜索下列位置:

/home/ry/projects/foo/node_modules/bar/node_modules/baz/node_modules/asdf.js
/home/ry/projects/foo/node_modules/bar/node_modules/asdf.js
/home/ry/projects/foo/node_modules/asdf.js
以文件夾作爲模塊
Node 允許用戶在獨立的目錄中方便地組織程序,然後提供單一入口指向該庫。有三種方式可以將文件夾作爲 require() 的參數。

第一種方式是在該文件夾中創建 package.json 文件,指定一個 main 模塊。一個典型的 package.json 文件可能看起來像這樣:

{ "name" : "some-library",
  "main" : "./lib/some-library.js" }如果此文件位於 ./some-library 文件夾,則 require('./some-library') 會嘗試加載 ./some-library/lib/some-library.js。

這是 Node 能找到 package.json 文件的情況。

如果在該目錄中沒有 package.json 文件,那麼 Node 將嘗試加載該目錄中的 index.js 或 index.node 文件。例如,如果上面的例子找不到 package.json,那麼 require('./some-library') 將試圖加載:

./some-library/index.js
./some-library/index.node
緩存
模塊在首次被加載後會緩存起來。這意味着每次調用 require('foo') 將得到完全相同的對象,如果它被解析爲同一個文件的話。

總結……
爲了得到調用 require() 時被載入的確切的文件名,使用 require.resolve() 函數。

綜上所述,這是 require.resolve 的僞碼描述:

require(X)
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with `./` or `/`,
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"

LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.node is a file, load X.node as binary addon.  STOP

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
2. LOAD_AS_FILE(X/index)

LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_AS_FILE(DIR/X)
   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let ROOT = index of first instance of "node_modules" in PARTS, or 0
3. let I = count of PARTS - 1
4. let DIRS = []
5. while I > ROOT,
   a. if PARTS[I] = "node_modules" CONTINUE
   c. DIR = path join(PARTS[0 .. I] + "node_modules")
   b. DIRS = DIRS + DIR
6. return DIRS從 `require.paths` 加載
在 Node 中,require.paths 是一個字符串數組,表示模塊不以 '/' './' 或 '..' 打頭的搜索路徑。例如,如果 require.paths 設置爲:

[ '/home/micheil/.node_modules',
  '/usr/local/lib/node_modules' ]則調用 require('bar/baz.js') 會搜索以下位置:

1: '/home/micheil/.node_modules/bar/baz.js'
2: '/usr/local/lib/node_modules/bar/baz.js'
可以在運行時修改 require.paths 數組來改變這種行爲。

它的值最初從 NODE_PATH 環境變量而來,那是一個冒號分隔的絕對路徑列表。在前面的例子中,NODE_PATH 環境變量可能被設置爲:

/home/micheil/.node_modules:/usr/local/lib/node_modules只有使用上面的 node_modules 算法找不到模塊時纔會嘗試 require.paths。全局模塊的優先級低於捆綁依賴。

**注意** 請不要修改 `require.paths`
出於兼容性的考慮,require.paths 仍然是模塊查找過程的首選策略。儘管如此,它可能會在將來的版本中廢棄。

雖然它看起來似乎是個好主意,但在實踐中一個可變的 require.paths 列表往往是麻煩和混亂的根源。

修改 `require.paths` 毫無用處
這行代碼並不會像期望的那樣:

require.paths = [ '/usr/lib/node' ];它的結果就是丟棄了 Node 實際的模塊查找路徑引用,並創建了一個毫無用處的指向別處的新的引用。

在 `require.paths` 中加入相對路徑……不是個好主意
如果你這樣做:

require.paths.push('./lib');它不會添加 ./lib 在文件系統上已解析的完整路徑。相反,它實際增加的是 './lib',這意味着如果你在 /a/b/x.js 中 require('y.js'),那麼它會查找 /a/b/lib/y.js。如果你之後又在 /l/m/n/o/p.js 中 require('y.js'),那麼它就會查找 /l/m/n/o/lib/y.js。

在實踐中,人們往往將它作爲捆綁依賴的臨時解決辦法,這個技巧是不太穩妥的。

零隔離
有一種糟糕的設計:所有模塊共用一個 require.paths 數組。

結果,如果一個 Node 程序依賴於這種行爲,它可能會永久而微妙地改變同一進程中其它 Node 程序的行爲。當應用程序的複雜度增加時,我們傾向於封裝功能,這些行爲很難預料的部分會成爲開發者的惡夢。

增編:軟件包管理小貼示
在 Node 中,require() 函數的語義被設計成通用性足以支持大量合理的目錄結構。因此 dpkg、rpm 和 npm 之類的包管理器可以從 Node 模塊構建原生包而不作更改。

下面我們給出一個可以工作的建議的目錄結構:

比方說,我們希望 /usr/lib/node/<some-package>/<some-version> 文件夾中包含某個包的特定版本的內容。

一個軟件包可以依賴別的包。爲了安裝 foo 包,你可能需要安裝 bar 包的特定版本 。可能該 bar 包本身有依賴關係,在某些情況下,這些依賴關係甚至可能發生衝突或者形成迴路。

由於 Node 在加載任何模塊時都會查找它的真實路徑(即:會解析符號鏈接),然後在 node_modules 文件夾用上文描述的方式查找依賴。使用以下架構可以很簡單地解決:

/usr/lib/node/foo/1.2.3/ -foo包的內容,版本1.2.3。
/usr/lib/node/bar/4.3.2/ -bar 包的內容,foo依賴這個包。
/usr/lib/node/foo/1.2.3/node_modules/bar -到 /usr/lib/node/bar/4.3.2/的符號鏈接。
/usr/lib/node/bar/4.3.2/node_modules/* -到 bar 所依賴的包的符號鏈接。
因此,即使遇到一個迴路,或者有依賴衝突,每個模塊都能夠得到它依賴的可用版本。

當 foo 包中有代碼 require('bar') 時,它會得到符號鏈接至 /usr/lib/node/foo/1.2.3/node_modules/bar 的版本。然後,當 bar 包調用 require('quux') 時,它會得到符號鏈接至 /usr/lib/node/bar/4.3.2/node_modules/quux 的版本。

此外,爲了使模塊查找過程更加優化,而​​不是直接把包放到 /usr/lib/node 中,我們可以它們放到 /usr/lib/node_modules/<name>/<version> 裏。這樣,Node 就不用在 /usr/node_modules 或 /node_modules 中查找了。

爲了使 REPL 能夠正常引用模塊,可以將 /usr/lib/node_modules 添加至 $NODE_PATH環境變量。因爲使用 node_modules 文件夾查找模塊時的路徑都是相對的,而且調用 require() 時基於文件的真實路徑,因此軟件包本身可以放在任何位置。

本篇文章來源於 Linux公社網站(www.linuxidc.com)  原文鏈接:http://www.linuxidc.com/Linux/2012-10/72627p2.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章