標簽(空格分隔): requireJS NodeJS
翻譯自官方文檔,英文地址,對翻譯內(nèi)容沒有把握,不負責(zé),孩子和我沒關(guān)系。
第一問:難道 Node 沒有一個模塊加載器么?
不,Node有。那個加載器使用CommonJS模塊樣式。CommonJS模塊樣式對瀏覽器不理想,并且我并不同意一些使用ConmmonJS模塊樣式建造的折中方案。通過在服務(wù)器端使用RequireJS,你可以使用一種樣式對你的所有模塊,無論他們是用于服務(wù)器端還是瀏覽器端。這種方式你可以保留速度優(yōu)勢并能輕松調(diào)試你得到的通過在瀏覽器端使用ReuqireJS,還能不用擔(dān)心由于兩種樣式的切換而帶來的額外轉(zhuǎn)換代價。
如果你想使用define()函數(shù)加載你的模塊,但是要在Node中運行,而不需要在服務(wù)器上運行RequireJS,看下一章節(jié)關(guān)于使用amddefine部分。
第二問:我能使用已經(jīng)用CommonJS模塊樣式寫好的Node模塊么?
能!關(guān)于RequireJS的Node適配器,叫做r.js。它將會使用Node的加載實現(xiàn)方法和Node的尋找路徑如果模塊根據(jù)ReuqireJS的配置沒有被找到,因此你能繼續(xù)使用你的已經(jīng)存在的基于Node的模塊不用去非要改變這些模塊。
RequireJS將會首先使用它的配置項去尋找模塊。如果RequireJS根據(jù)配置項沒有找到模塊,這個模塊就會被假定使用Node模塊的樣式和配置。因此,只有用RequireJS配置模塊位置如果使用了RequireJS的API。對于想使用Node的API和配置路徑的模塊來說,僅僅使用Node包管理器,例如npm安裝他們即可,不要用RequireJS來配置他們的路徑。
最佳實踐:使用npm安裝Node-only的包/模塊到項目中node_modules的項目目錄中去,但是不要配置RequireJS去在node_modules目錄中尋找。同樣避免使用相對的模塊ID去查閱Node-only的模塊。因此,不要做這樣的事類似于
require("./node_modules/foo/foo");
最后,RequireJS在Node中僅能加載在本地磁盤的模塊,比如通過HTTP來提取模塊,目前還是不允許。
第三問:我該怎么使用它?
有兩種方法來獲取Node適配器
1.npm
使用npm來安裝它
npm install requirejs
這種操作能夠安裝最新的發(fā)布版
2.下載 r.js
如果你更傾向不使用npm,你可以直接獲取r.js。
用法
以下的使用說明是建立在安裝了requirejs的基礎(chǔ)上的,如果你正在直接使用r.js,把require('requirejs')替換為require('./path/to/r.js')
基礎(chǔ)用法為:
- require('requirejs')
- 將主要js文件的require函數(shù)傳遞給requirejs的配置項
例子:
var requirejs = require('requirejs');
requirejs.config({
//將最頂層的main.js/index.js的require函數(shù)傳遞給requirejs以至于 node模塊相對于頂級JS文件加載
nodeRequire:require
});
requirejs(['foo','bar'],function(foo,bar){
//foo和bar通過requirejs的額配置項加載,但是如果沒有被找到,那么將使用node的require方法來加載模塊
});
確保已經(jīng)閱讀過位于第二部分的關(guān)于配置requireJS的提示,因此可以加載通過npm安裝的node-only模塊。
想看更多完整的關(guān)于使用RequireJS加載模塊,但是使用node原生模塊去做其他事情的事例,參考embedded test位于r.js的倉庫中。
注意:requirejs([],function(){})采用異步調(diào)用回調(diào)函數(shù)在RequireJS 2.1+的版本中。(早期版本為同步調(diào)用)。然而,當在Node中運行時,模塊加載被載入采用同步IO調(diào)用,加載器插件應(yīng)該同時決定加載方法的調(diào)用。這允許同時在node中使用requirejs通過requirejs('stringValue')調(diào)用。
//同步檢索值為a的模塊
var a = requirejs('a');
搭建node模塊使用AMD和RequrireJS
如果你想編寫一個模塊使其在Node中使用RequireJS工作,但并不需要庫的使用者們在Node中使用RequireJS,那么你可以使用amdefine包去實現(xiàn):
if(typeof define !== 'function'){
var define = require('amdefine')(module);
}
define(function(require){
var dep = require('dependency');
//這個從函數(shù)返回的值被用作模塊導(dǎo)出并可見于Node
return function(){};
});
RequireJS優(yōu)化器,自版本1.0.3起,將會去掉上述'amdfine'的使用,因此它也同樣對于你的基于網(wǎng)絡(luò)的模塊是安全的。只需要確定使用上述代碼中嚴格的'amdefine' if()檢測和內(nèi)容??崭?換行的區(qū)別是允許的。查看amdefine project獲取更多信息。
如果你想直接使用RequireJS去編碼你的模塊,然后導(dǎo)出一個模塊值給node使之能在其他Node項目中使用并且不需要app使用RequireJS,你可以使用列在下一個例子中的方法。
最好去明確的設(shè)置baseUrl相對于包含這個模塊的目錄,以便能正常工作當模塊被嵌套早node_modules層。使用同步的requirejs('moduleId')去尋找使用了requirejs配置和規(guī)則的模塊,然后用Node模塊的module.exports去導(dǎo)出模塊值:
var requirejs = require('requirejs');
requirejs.config({
//使用node的特殊變量 __dirname 去獲得包含這個文件的目錄
//如果構(gòu)建將在節(jié)點中使用但不需要使用外部節(jié)點的庫,則非常有用(搜狗翻譯)
baseUrl : __dirname,
//將頂層的main.js/index.js require函數(shù)傳遞給requirejs以便node模塊相對頂層JS文件去加載
nodeRequire : require
});
//foo和bar通過requirejs的配置加載,如果被找到,被假定是一個AMD模塊。如果沒有通過requirejs的配置找到foo和bar,那么用node的require去加載模塊,若此時被找到,這個模塊就會被認為是node模式的模塊。注意:加載模塊的同步方式只在node中有效。
var foo = requirejs('foo');
var bar = requirejs('bar');
//導(dǎo)出一個對Node可見的值
module.exports = function(){};
使用優(yōu)化器作為node模塊
為了通過函數(shù)調(diào)用而不是命令行工具來使用RequireJS optimizer,node模塊也將RequireJS Optimizer公開為最優(yōu)化的方法。
var requirejs = require('requirejs');
var config = {
baseUrl : '../appDir/scripts',
name:'main',
out:'../build/main-built.js'
};
requirejs.optimize(config,function(buildResponse){
//buildResponse是一個包含模塊的文本輸出。給contents加載生成的文件。使用config.out來獲得優(yōu)化后的文件內(nèi)容
var contents = fs.readFileSync(config.out,'utf8');
},function(err){
//優(yōu)化后錯誤回調(diào)
});
這能讓你構(gòu)造其他的最優(yōu)化工作流程,比如可以使用a web builder,如果你更喜歡用“< /body>標簽前包含一個腳本文件”去開發(fā)的話。這個優(yōu)化器在Node中的運行相當迅速,只針對那些在每次瀏覽器請求時不想重新生成構(gòu)造文件的大型項目,也只在你修改的腳本屬于這些構(gòu)造文件的情況下。你可以使用Node的fs.watchFile()去監(jiān)測文件,然后當文件變化時觸發(fā)文件的重新構(gòu)造。