什麼是模組化?本篇文章帶大家了解一下Node中的模組化,介紹一下模組的載入機制,希望對大家有幫助!
1.1 什麼是模組化
模組化是指解決一個複雜問題時,自頂向下逐層把系統劃分成若干模組的過程。對於整個系統來說,模組是可組合、分解和更換的單元。
程式設計領域中的模組化,就是遵守固定的規則,把一個大檔案拆成獨立並互相依賴的多個小模組。
把程式碼進行模組化分割的好處:
提高了程式碼的複用性
提高了程式碼的可維護性
可以實作按需載入
#2.1 Node.js 中模組的分類
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 moment@2.22.24、套件的語意化版本規範#套件的版本號碼是以「點分十進制」形式定義的,總共有三位數字,例如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 (套件中的說明文件)
README.md (套件的說明文件)
註:name—用於告知應用程式或軟體包的名稱;version—表明了目前的版本;main —設定了應用程式的入口點;description是應用程式/軟體包的簡短描述;keywords—此屬性包含與軟體包功能相關的關鍵字數組(有助於瀏覽node官網找到該軟體包);license—指定軟體包的許可證。##2、初始化package.json
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
(3)C:\Users\node_modules\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/7083445004240158757nodejs 教學###! ###
以上是深入聊聊Node.js中的模組化的詳細內容。更多資訊請關注PHP中文網其他相關文章!