爲了統一 Javascript 在瀏覽器以外的實現,CommonJS 誕生了,CommonJS 試圖定義一套普通應用程序使用的 API,從而填補 JavaScript 標準庫過於簡單的不足。 CommonJS 規範包括了模塊、包、系統、控制檯、文件系統、單元測試等部分。javascript
Node.js 是目前 CommonJS 規範最熱門的一個實現,隨着 CommonJS 規範的更新,Node.js 也在不斷跟進 ,但 Node.js 並不徹底遵循 CommonJS 規範。這是全部規範制定者都會遇到的尷尬局面,由於規範的制定老是滯後於技術的發展。html
模塊(Module)和包(Package)是 Node.js 最重要的支柱,開發一個具備必定規模的程序不可能只用一個文件,一般須要把各個功能拆分、封裝,而後組合起來,模塊正是爲了實現這種方式而誕生。
在瀏覽器 JavaScript 中,腳本模塊的拆分和組合一般使用 HTML 的 script 標籤來實現。Node.js 提供了 require 函數來調用其餘模塊,並且模塊都是基於文件的,換句話說就是每一個文件都是一個模塊,機制十分簡單。java
nodejs的模塊能夠分爲兩類,一類是核心模塊,另外一類是文件模塊。node
核心模塊是 nodejs 官方提供的,node 進程啓動時,部分核心模塊就被直接加載進內存中, 因此這部分核心模塊咱們就能夠直接經過require 進行引入。好比 http 模塊、url 模塊、fs 模塊等。git
const http = require('http'); // 內置模塊直接引用 const host = '127.0.0.1'; const port = 3000; const server = http.createServer((req,res) => { res.statusCode = 200; res.end('test1'); }) server.listen(port, host, () => { console.log(`服務器運行在 http://${host}:${port}/`) })
文件模塊是在運行時動態加載,須要完整的路徑分析、文件定位、編譯執行過程、速度相比核心模塊稍微慢一些, 可是用的很是多。文件模塊的加載方式有兩種,一種是按路徑加載,另外一種是查找node_modules
文件夾。github
按路徑加載模式express
// custom_module文件夾下的tools文件 function calculate(num) { return num*2 } function getUrl(domain) { return `${domain}/wanwan0306` } module.exports = { calculate, getUrl } // app.js const http = require('http'); const { calculate, getUrl } = require('./custom_module/tools'); // 按路徑引入 const host = '127.0.0.1'; const port = 3100; const server = http.createServer((req,res) => { const num = calculate(20); const url = getUrl('https'); res.statusCode = 200; res.end(`${num}-${url}-test2`); }) server.listen(port, host, () => { console.log(`服務器運行在 http://${host}:${port}/`) })
node_modules文件夾加載模式npm
// node_modules文件夾下的tools文件 function calculate(num) { return num*2 } function getUrl(domain) { return `${domain}/wanwan0306` } module.exports = { calculate, getUrl } // app.js const http = require('http'); const { calculate, getUrl } = require('tools'); // node_modules const host = '127.0.0.1'; const port = 3200; const server = http.createServer((req,res) => { const num = calculate(20); const url = getUrl('https'); res.statusCode = 200; res.end(`${num}-${url}-test3`); }) server.listen(port, host, () => { console.log(`服務器運行在 http://${host}:${port}/`) })
1.若是 require 參數字符串以「/」開頭,則表示加載的是一個位於絕對路徑的模塊文件, 好比,require('/future/Demo/NodeJs/2.模塊化/custom_module/tools.js')
將加載/future/Demo/NodeJs/2.模塊化/custom_module/tools.js
;json
2.若是 require 參數以「 ./ 」或「 ../ 」開頭,那麼則以相對路徑的方式來查找模塊,這種方式在應用中是最多見的, 例如前面的例子中咱們用了require('./custom_module/tools')
來加載;瀏覽器
3.若是require參數不以「 ./ 」或「 ../ 」開頭,而該模塊又不是核心模塊,那麼就要經過查找 node_modules
來加載模塊了(使用npm獲取的包一般就是以這種方式加載的);
舉例來講:腳本/future/Demo/NodeJs/2.模塊化/app3.js
執行了require('tools.js')
命令,Node會依次搜索如下文件。
/usr/local/lib/node/tools.js /future/Demo/NodeJs/2.模塊化/node_modules/tools.js /future/Demo/NodeJs/node_modules/tools.js /future/node_modules/tools.js /node_modules/tools.js
4.若是指定的模塊文件沒有後綴,Node 會嘗試爲文件名添加.js、.json、.node
後,再去搜索。 .js 件會以文本格式的JavaScript 腳本文件解析,.json 文件會以 JSON 格式的文本文件解析,.node 文件會以編譯後的二進制文件解析;
注意:核心模塊擁有最高的加載優先級,換言之若是有模塊與其命名衝突,Node.js 老是會加載核心模塊。
Node.js 模塊不會被重複加載,這是由於 Node.js 經過文件名緩存全部加載過的文件模塊,因此之後再訪問到時就不會從新加載了,注意,Node.js 是根據實際文件名緩存的,而不是 require() 提供的參數緩存的,也就是說即便你分別經過require('tools')
和 require('./node_modules/tools')
加載兩次,也不會重複加載,由於儘管兩次參數不一樣,解析到的文件倒是同一個。
npm 是隨同 NodeJS 一塊兒安裝的包管理工具,能解決 NodeJS 代碼部署上的不少問題,常見的使用場景有如下幾種:
使用 npm 命令安裝模塊,使用使用語法以下
npm install express // 本地安裝 npm install express -g // 全局安裝
本地安裝
./node_modules
下(運行 npm 命令時所在的目錄),若是沒有 node_modules
目錄,會在當前執行 npm 命令的目錄下生成 node_modules
目錄。全局安裝
/usr/local
下或者你 node
的安裝目錄。package.json用於定義包的屬性,接下來咱們來建立下:
$ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (2.模塊化) test //模塊名 version: (1.0.0) description: nodejs模塊化demo //項目描述 entry point: (app1.js) test command: git repository: keywords: author: wanwan license: (ISC) About to write to /xx/package.json: { "name": "test", "version": "1.0.0", "description": "nodejs模塊化demo", "main": "app1.js", "dependencies": { "express": "^4.17.1" }, "devDependencies": {}, "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "author": "wanwan", "license": "ISC" } Is this OK? (yes) yes
npm經常使用指令
npm version 查看模塊版本 npm help 查看某條命令的詳細幫助 npm install 安裝模塊 npm uninstall 卸載模塊 npm update 更新模塊 npm outdated 檢查模塊是否已通過時 npm ls 查看安裝的模塊 npm init 在項目中引導建立一個package.json文件
完整示例代碼:https://github.com/wanwan0306/future/tree/master/Demo/NodeJs/2.模塊化