1.1 什麼是模組化
模組化是指解決一個複雜問題時,自頂向下逐層把系統劃分成若干模組的過程。對於整個系統來說,模組是可組合、分解和更換的單元。
程式設計領域中的模組化,就是遵守固定的規則,把一個大檔案拆成獨立並互相依賴的多個小模組。
把程式碼進行模組化拆分的好處:
提高了程式碼的複用性
提高了程式碼的可維護性
可以實現按需載入
2.1 Node.js 中模組的分類
中根據模組來源的不同,將模組分為了 3 大類,分別是:
內建模組(內建模組是由 Node.js 官方提供的,例如 fs、path、http 等)
自定義模組(使用者建立的每個 .js 檔案,都是自定義模組)
第三方模組(由第三方開發出來的模組,並非官方提供的內建模組,也不是使用者建立的自定義模組,使用前需要先下載)
2.2 載入模組
使用強大的 require() 方法,可以載入需要的內建模組、使用者自定義模組、第三方模組進行使用。例如:
注意:使用 require() 方法載入其它模組時,會執行被載入模組中的程式碼; 載入自定義模組可以省略檔案字尾名'.js'。
2.3 Node.js 中的模組作用域
什麼是模組作用域
和函數作用域類似,在自定義模組中定義的變數、方法等成員,只能在當前模組內被存取,這種模組級別的存取限制,叫做模組作用域。
模組作用域的好處
防止了全域性變數汙染的問題(如果用script標籤匯入兩個js檔案且兩個檔案中都定義了同一個變數,則前一個會被後一個覆蓋)
2.4 向外共用模組作用域中的成員
1、module 物件
在每個 .js 自定義模組中都有一個 module 物件,它裡面儲存了和當前模組有關的資訊,列印如下:
2、module.exports 物件
在自定義模組中,可以使用 module.exports 物件,將模組內的成員共用出去,供外界使用。
外界用 require() 方法匯入自定義模組時,得到的就是 module.exports 所指向的物件。
3、共用成員時的注意點
使用 require() 方法匯入模組時,匯入的結果,永遠以 module.exports 指向的物件為準。
4. exports 物件
由於 module.exports 單詞寫起來比較複雜,為了簡化向外共用成員的程式碼,Node 提供了 exports 物件。預設情況下,exports 和 module.exports 指向同一個物件。最終共用的結果,還是以 module.exports 指向的物件為準。
5. exports 和 module.exports 的使用誤區
時刻謹記,require() 模組時,得到的永遠是 module.exports 指向的物件:
個人理解:exports 和 module.exports本來指向同一個物件。僅僅通過掛載資料指向的還是同一個物件,通過exports掛載的資料也可以被require模組得到。如果一方賦值(指向另一個物件,那麼他們就不指向同一物件了,而require模組得到的是module.exports 指向的物件,所以一旦一方改變指向,require模組就不會得到exports的值。)
注意:為了防止混亂,建議大家不要在同一個模組中同時使用 exports 和 module.exports
2.5 Node.js 中的模組化規範Node.js 遵循了 CommonJS 模組化規範,CommonJS 規定了模組的特性和各模組之間如何相互依賴。
CommonJS 規定:
(1)每個模組內部,module 變數代表當前模組。
(2)module 變數是一個物件,它的 exports 屬性(即 module.exports)是對外的介面。
(3)載入某個模組,其實是載入該模組的 module.exports 屬性。require() 方法用於載入模組。
3.1 包
1、什麼是包
Node.js 中的第三方模組又叫做包。
就像電腦和計算機指的是相同的東西,第三方模組和包指的是同一個概念,只不過叫法不同。
2、包的來源
不同於 Node.js 中的內建模組與自定義模組,包是由第三方個人或團隊開發出來的,免費供所有人使用。
注意:Node.js 中的包都是免費且開源的,不需要付費即可免費下載使用。
3、為什麼需要包
由於 Node.js 的內建模組僅提供了一些底層的 API,導致在基於內建模組進行專案開發的時,效率很低。
包是基於內建模組封裝出來的,提供了更高階、更方便的 API,極大的提高了開發效率。
包和內建模組之間的關係,類似於 jQuery 和 瀏覽器內建 API 之間的關係。
4、從哪裡下載包
國外有一家 IT 公司,叫做 npm, Inc. 這家公司旗下有一個非常著名的網站: www.npmjs.com/ ,它是全球最大的包共用平臺,你可以從這個網站上搜尋到任何你需要的包,只要你有足夠的耐心!
到目前位置,全球約 1100 多萬的開發人員,通過這個包共用平臺,開發並共用了超過 120 多萬個包 供我們使用。 npm, Inc. 公司提供了一個地址為 registry.npmjs.org/ 的伺服器,來對外共用所有的包,我們可以從這個伺服器上下載自己所需要的包。
注意:
從 www.npmjs.com/ 網站上搜尋自己所需要的包
從 registry.npmjs.org/ 伺服器上下載自己需要的包
5、如何下載包
npm, Inc. 公司提供了一個包管理工具,我們可以使用這個包管理工具,從 registry.npmjs.org/ 伺服器把需要的包下載到本地使用。
這個包管理工具的名字叫做 Node Package Manager(簡稱 npm 包管理工具),這個包管理工具隨著 Node.js 的安裝包一起被安裝到了使用者的電腦上。
大家可以在終端中執行 npm -v 命令,來檢視自己電腦上所安裝的 npm 包管理工具的版本號:
3.2 npm 初體驗
1、在專案中安裝包的命令
如果想在專案中安裝指定名稱的包,需要執行如下的命令:
npm install 包的完整名稱
上述的裝包命令,可以簡寫成如下格式:
npm i 包的完整名稱
2、初次裝包後多了哪些檔案
初次裝包完成後,在專案資料夾下多一個叫做 node_modules 的資料夾和 package-lock.json 的組態檔。
其中: node_modules 資料夾用來存放所有已安裝到專案中的包。require() 匯入第三方包時,就是從這個目錄中查詢並載入包。
package-lock.json 組態檔用來記錄 node_modules 目錄下的每一個包的下載資訊,例如包的名字、版本號、下載地址等。
注意:程式設計師不要手動修改 node_modules 或 package-lock.json 檔案中的任何程式碼,npm 包管理工具會自動維護它們。
3、安裝指定版本的包
預設情況下,使用 npm install 命令安裝包的時候,會自動安裝最新版本的包。如果需要安裝指定版本的包,可以在包名之後,通過 @ 符號指定具體的版本,例如:
npm i [email protected]
4、包的語意化版本規範
包的版本號是以「點分十進位制」形式進行定義的,總共有三位數位,例如 2.24.0
其中每一位數位所代表的的含義如下:
第1位數位:大版本
第2位數位:功能版本
第3位數位:Bug修復版本
版本號提升的規則:只要前面的版本號增長了,則後面的版本號歸零。
3.3 包管理組態檔
npm 規定,在專案根目錄中,必須提供一個叫做 package.json 的包管理組態檔。用來記錄與專案有關的一些設定資訊。例如:
專案的名稱、版本號、描述等
專案中都用到了哪些包
哪些包只在開發期間會用到
那些包在開發和部署時都需要用到
1、多人共同作業的問題
遇到的問題:第三方包的體積過大,不方便團隊成員之間共用專案原始碼。
解決方案:共用時剔除node_modules
2、如何記錄專案中安裝了哪些包
在專案根目錄中,建立一個叫做 package.json 的組態檔,即可用來記錄專案中安裝了哪些包。從而方便剔除 node_modules 目錄之後,在團隊成員之間共用專案的原始碼。
注意:今後在專案開發中,一定要把 node_modules 資料夾,新增到 .gitignore 忽略檔案中。
3、快速建立 package.json
npm 包管理工具提供了一個快捷命令,可以在執行命令時所處的目錄中,快速建立 package.json 這個包管理組態檔:
npm init -y
注意:
(1)上述命令只能在英文的目錄下成功執行!所以,專案資料夾的名稱一定要使用英文命名,不要使用中文,不能出現空格。
(2)@執行 npm install 命令安裝包的時候,npm 包管理工具會自動把包的名稱和版本號,記錄到 package.json 中。
4、dependencies 節點
package.json 檔案中,有一個 dependencies 節點,專門用來記錄您使用 npm install 命令安裝了哪些包。
5、一次性安裝所有的包
當我們拿到一個剔除了 node_modules 的專案之後,需要先把所有的包下載到專案中,才能將專案執行起來。 否則會報類似於下面的錯誤:
可以執行 npm install 命令(或 npm i)一次性安裝所有的依賴包:
6、解除安裝包
可以執行 npm uninstall 命令,來解除安裝指定的包:
npm uninstall 具體的包名
注意:npm uninstall 命令執行成功後,會把解除安裝的包,自動從 package.json 的 dependencies 中移除掉。解除安裝沒有簡寫。
7、devDependencies 節點
如果某些包只在專案開發階段會用到,在專案上線之後不會用到,則建議把這些包記錄到 devDependencies 節點中。
與之對應的,如果某些包在開發和專案上線之後都需要用到,則建議把這些包記錄到 dependencies 節點中。
您可以使用如下的命令,將包記錄到 devDependencies 節點中:
3.4 解決下包速度慢的問題
1、為什麼下包速度慢
在使用 npm 下包的時候,預設從國外的 registry.npmjs.org/ 伺服器進行下載,因此下包速度會很慢。
2、淘寶 NPM 映象伺服器
淘寶在國內搭建了一個伺服器,專門把國外官方伺服器上的包同步到國內的伺服器,然後在國內提供下包的服務。從而極大的提高了下包的速度。
擴充套件: 映象(Mirroring)是一種檔案儲存形式,一個磁碟上的資料在另一個磁碟上存在一個完全相同的副本即為映象。
3、切換 npm 的下包映象源
下包的映象源,指的就是下包的伺服器地址。
4、nrm
為了更方便的切換下包的映象源,我們可以安裝 nrm 這個小工具,利用 nrm 提供的終端命令,可以快速檢視和切換下包的映象源。
3.5 包的分類
使用 npm 包管理工具下載的包,共分為兩大類,分別是:
專案包
全域性包
1、專案包
那些被安裝到專案的 node_modules 目錄中的包,都是專案包。
專案包又分為兩類,分別是:
開發依賴包(被記錄到 devDependencies 節點中的包,只在開發期間會用到)
核心依賴包(被記錄到 dependencies 節點中的包,在開發期間和專案上線之後都會用到)
2、全域性包 在執行 npm install 命令時,如果提供了 -g 引數,則會把包安裝為全域性包。
全域性包會被安裝到 C:\Users\使用者目錄\AppData\Roaming\npm\node_modules 目錄下。
注意:
(1)只有工具性質的包,才有全域性安裝的必要性。因為它們提供了好用的終端命令。
(2)判斷某個包是否需要全域性安裝後才能使用,可以參考官方提供的使用說明即可。
3、i5ting_toc
i5ting_toc 是一個可以把 md 檔案轉為 html 頁面的小工具,使用步驟如下:
3.6 規範的包結構
在清楚了包的概念、以及如何下載和使用包之後,接下來,我們深入瞭解一下包的內部結構。
一個規範的包,它的組成結構,必須符合以下 3 點要求:
(1)包必須以單獨的目錄而存在
(2)包的頂級目錄下要必須包含 package.json 這個包管理組態檔
(3)package.json 中必須包含 name,version,main 這三個屬性,分別代表包的名字、版本號、包的入口。
注意:以上 3 點要求是一個規範的包結構必須遵守的格式,關於更多的約束,可以參考如下網址:https://yarnpkg.com/zh-Hans/docs/package-json
3.7 開發屬於自己的包
1、初始化包的基本結構
(1)新建一個itheima-tools資料夾,作為包的根目錄
(2)在itheima-tools資料夾中,新建如下三個檔案:
package.json (包管理組態檔)
index.js (包的入口檔案)
README.md (包的說明檔案)
2、初始化 package.json
注:name—用於告知應用程式或軟體包的名稱;version—表明了當前的版本;main—設定了應用程式的入口點;description是應用程式/軟體包的簡短描述;keywords—此屬性包含與軟體包功能相關的關鍵字陣列(有助於瀏覽node官網找到該軟體包);license—指定軟體包的許可證。
3、編寫包的說明檔案
包根目錄中的 README.md 檔案,是包的使用說明檔案。通過它,我們可以事先把包的使用說明,以 markdown 的格式寫出來,方便使用者參考。
README 檔案中具體寫什麼內容,沒有強制性的要求;只要能夠清晰地把包的作用、用法、注意事項等描述清楚即可。
3.8 釋出包
1、註冊 npm 賬號
(1)存取 www.npmjs.com/ 網站,點選 sign up 按鈕,進入註冊使用者介面
(2)填寫賬號相關的資訊:Full Name、Public Email、Username、Password
(3)點選 Create an Account 按鈕,註冊賬號
(4)登入郵箱,點選驗證連結,進行賬號的驗證
2、登入 npm 賬號
npm 賬號註冊完成後,可以在終端中執行 npm login 命令,依次輸入使用者名稱、密碼(密碼是隱藏的,看不到,只管輸入正確回車即可)、郵箱、傳送到郵箱的OTP code後,即可登入成功。
注意:在執行 npm login 命令之前,必須先把下包的伺服器地址切換為 npm 的官方伺服器。(如果之前是用的taobao伺服器一定要切換為npm官方伺服器)否則會導致釋出包失敗!
3、把包釋出到 npm 上
將終端切換到包的根目錄之後,執行 npm publish 命令,即可將包釋出到 npm 上(注意:包名不能雷同,可以去官網查是否有重名的包)。
4、刪除已釋出的包
執行 npm unpublish 包名 --force 命令,即可從 npm 刪除已釋出的包。
注意:
(1)npm unpublish 命令只能刪除 72 小時以內釋出的包
(2)npm unpublish 刪除的包,在 24 小時內不允許重複釋出
(3)釋出包的時候要慎重,儘量不要往 npm 上釋出沒有意義的包!
4.1 優先從快取中載入
模組在第一次載入後會被快取。 這也意味著多次呼叫 require() 不會導致模組的程式碼被執行多次。
注意:不論是內建模組、使用者自定義模組、還是第三方模組,它們都會優先從快取中載入,從而提高模組的載入效率。
4.2 內建模組的載入機制
內建模組是由 Node.js 官方提供的模組,內建模組的載入優先順序最高。
例如:require('fs') 始終返回內建的 fs 模組,即使在 node_modules 目錄下有名字相同的包也叫做 fs。
4.3 自定義模組的載入機制
使用 require() 載入自定義模組時,必須指定以 ./ 或 ../ 開頭的路徑識別符號。在載入自定義模組時,如果沒有指定 ./ 或 ../ 這樣的路徑識別符號,則 node 會把它當作內建模組或第三方模組進行載入。
同時,在使用 require() 匯入自定義模組時,如果省略了檔案的擴充套件名,則 Node.js 會按順序分別嘗試載入以下的檔案:
(1)按照確切的檔名進行載入
(2)補全 .js 擴充套件名進行載入
(3)補全 .json 擴充套件名進行載入
(4)補全 .node 擴充套件名進行載入
(5)載入失敗,終端報錯
4.4 第三方模組的載入機制
如果傳遞給 require() 的模組識別符號不是一個內建模組,也沒有以 ‘./’ 或 ‘../’ 開頭,則 Node.js 會從當前模組的父目錄開始,嘗試從 /node_modules 資料夾中載入第三方模組。
如果沒有找到對應的第三方模組,則移動到再上一層父目錄中,進行載入,直到檔案系統的根目錄。
例如,假設在 'C:\Users\itheima\project\foo.js' 檔案裡呼叫了 require('tools'),則 Node.js 會按以下順序查詢:
(1)C:\Users\itheima\project\node_modules\tools
(2)C:\Users\itheima\node_modules\tools
(3)C:\Users\node_modules\tools
(4)C:\node_modules\tools
4.5 目錄作為模組
當把目錄作為模組識別符號,傳遞給 require() 進行載入的時候,有三種載入方式:
(1)在被載入的目錄下查詢一個叫做 package.json 的檔案,並尋找 main 屬性,作為 require() 載入的入口
(2)如果目錄裡沒有 package.json 檔案,或者 main 入口不存在或無法解析,則 Node.js 將會試圖載入目錄下的 index.js 檔案。
(3)如果以上兩步都失敗了,則 Node.js 會在終端列印錯誤訊息,報告模組的缺失:Error: Cannot find module 'xxx'
本文轉載自:https://juejin.cn/post/7083445004240158757
更多node相關知識,請存取:!
以上就是深入聊聊Node.js中的模組化的詳細內容,更多請關注TW511.COM其它相關文章!