node系列:2、模塊化

image

1、寫在前面

爲了統一 Javascript 在瀏覽器以外的實現,CommonJS 誕生了,CommonJS 試圖定義一套普通應用程序使用的 API,從而填補 JavaScript 標準庫過於簡單的不足。 CommonJS 規範包括了模塊、包、系統、控制檯、文件系統、單元測試等部分。javascript

Node.js 是目前 CommonJS 規範最熱門的一個實現,隨着 CommonJS 規範的更新,Node.js 也在不斷跟進 ,但 Node.js 並不徹底遵循 CommonJS 規範。這是全部規範制定者都會遇到的尷尬局面,由於規範的制定老是滯後於技術的發展。html

2、node模塊化

模塊(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.jsjson

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

npm官網https://www.npmjs.cn/

npm 是隨同 NodeJS 一塊兒安裝的包管理工具,能解決 NodeJS 代碼部署上的不少問題,常見的使用場景有如下幾種:

  1. 容許用戶從 npm 服務器下載別人編寫的第三方包到本地使用。
  2. 容許用戶從 npm 服務器下載並安裝別人編寫的命令行程序到本地使用。
  3. 容許用戶將本身編寫的包或命令行程序上傳到NPM服務器供別人使用。

使用 npm 命令安裝模塊,使用使用語法以下

npm install express      // 本地安裝
npm install express -g   // 全局安裝

本地安裝

  1. 將安裝包放在 ./node_modules 下(運行 npm 命令時所在的目錄),若是沒有 node_modules 目錄,會在當前執行 npm 命令的目錄下生成 node_modules 目錄。
  2. 能夠經過 require() 來引入本地安裝的包。

全局安裝

  1. 將安裝包放在 /usr/local 下或者你 node 的安裝目錄。
  2. 能夠直接在命令行裏使用。

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文件

4、參考資料

  1. Nodejs開發指南.pdf
  2. Node學習指南.pdf
  3. CommonJS規範 -- JavaScript 標準參考教程(alpha)

完整示例代碼:https://github.com/wanwan0306/future/tree/master/Demo/NodeJs/2.模塊化

相關文章
相關標籤/搜索