Node.js 中的一個(gè)重要概念是您想知道依賴管理的處理方式。這種依賴管理是 Node.js 核心體驗(yàn)的一部分。在這篇文章中,我們將學(xué)習(xí)依賴管理的各種模式以及 Nodejs 如何加載依賴。
因此,我們可以為所有內(nèi)容使用單個(gè)js 文件編寫我們的應(yīng)用程序,但這不是模塊化的。Node.js 使編寫模塊化代碼變得非常簡(jiǎn)單。
在我們深入研究細(xì)節(jié)之前,首先要回答的問題是模塊。它是什么?我們?yōu)槭裁匆P(guān)心它?
簡(jiǎn)單來說,一個(gè)模塊就是一段代碼,我們將它們組合在一起,以便共享和重用。因此,模塊允許我們將應(yīng)用程序中的復(fù)雜性分解為小塊。這有助于理解代碼直至查找和修復(fù)錯(cuò)誤。如果你想了解更多關(guān)于 JavaScript 模塊系統(tǒng)的信息,你可以查看這篇 文章。
Node 使用一種工具來要求 某些行為。這是基于 CommonJS 的。簡(jiǎn)而言之,為了引入 JavaScript 文件,我們使用關(guān)鍵字require。
我假設(shè)您已經(jīng)了解 Nodejs 的一些基礎(chǔ)知識(shí)。如果您是 Nodejs 新手,您還可以查看我之前的文章Node.js – Introduction了解一些背景信息。
設(shè)置應(yīng)用程序
讓我們從簡(jiǎn)單的開始。我為項(xiàng)目創(chuàng)建了一個(gè)目錄,使用npm init 對(duì)其進(jìn)行初始化,并創(chuàng)建了兩個(gè) JavaScript 文件(app.js 和 appMsg.js)。這就是投影的樣子,我們將以此作為演示的起點(diǎn)。此外,您可以從文章后面提到的 git repo 鏈接下載最終代碼。
此時(shí),兩個(gè) .js 文件都是空的。讓我們用以下更改更新appMsgs.js文件:
我們可以看到module.exports關(guān)鍵字的使用。此語法用于公開給定文件 (appMsgs.js) 中的屬性或?qū)ο螅缓罂梢栽诹硪粋€(gè)文件中使用這些屬性或?qū)ο?,在我們的示例中為app.js。
在這個(gè)系統(tǒng)中,每個(gè)文件都可以訪問稱為module.exports. 因此,我們?cè)?appMsgs.js 文件中公開了一些項(xiàng)目,現(xiàn)在讓我們看看app.js如何使用(需要)這些屬性:
現(xiàn)在要引用文件,我們使用require關(guān)鍵字。當(dāng)我們 時(shí)require,它將返回一個(gè)對(duì)象,該對(duì)象將表示該模塊化代碼段,因此我們將其分配給一個(gè)變量appMsgs變量,然后在console.log語句中簡(jiǎn)單地使用屬性。當(dāng)我們執(zhí)行代碼時(shí),我們可以看到以下輸出:
所以,這 require是在執(zhí)行 JavaScript,允許它構(gòu)造一個(gè)返回給我們的具有一些功能的對(duì)象。
這可能是一個(gè)類構(gòu)造函數(shù)或一個(gè)對(duì)象,其中包含許多元素或一些簡(jiǎn)單的屬性。這有不同的模式,我們可以導(dǎo)出不止一件東西,甚至導(dǎo)出復(fù)雜的對(duì)象。
因此,通過管理require和module.exports,我們可以創(chuàng)建這些模塊化應(yīng)用程序。
所需的功能加載代碼并加載一次。因此,無論在這里執(zhí)行什么代碼,都不會(huì)第二次執(zhí)行。因此,如果其他人通過 請(qǐng)求此對(duì)象require,它將獲得此對(duì)象的緩存版本。讓我們看看其他一些方法。
我已經(jīng)更改了代碼,現(xiàn)在不是公開對(duì)象,而是導(dǎo)出function. 每次作為函數(shù)調(diào)用時(shí)都會(huì)執(zhí)行此代碼。
接下來我們看看它在app.js文件中是如何使用的:
我們可以像執(zhí)行函數(shù)一樣執(zhí)行它,而不是調(diào)用屬性。所以,這里的區(qū)別在于,每次我們執(zhí)行這段代碼時(shí),都會(huì)重新執(zhí)行函數(shù)內(nèi)部的代碼。
這是我們運(yùn)行代碼時(shí)的輸出:
所以,我們已經(jīng)看到了兩種模式module.exports 和它們的區(qū)別。另一個(gè)常見的模式,你會(huì)想知道使用 this 作為構(gòu)造函數(shù) 方法。讓我們看一個(gè)例子:
這是更新后的app.js文件:
因此,這與在 JavaScript 中創(chuàng)建偽類 并允許創(chuàng)建它的實(shí)例 時(shí)本質(zhì)上是相同的。
這是此更改的輸出:
現(xiàn)在,讓我們看看這些模式的另一個(gè)例子:
我創(chuàng)建了一個(gè)名為userRepo.js的新文件,如下所示:
這是此更改的app.js和執(zhí)行結(jié)果:
對(duì)單個(gè)文件使用require并不少見,但您還應(yīng)該注意另一種模式。接下來讓我們看看文件夾的依賴關(guān)系。
文件夾依賴
我們將退后一步,了解 Nodejs 如何查找依賴項(xiàng)。記住前面例子中的那句話:
JavaScript:
var appMsgs = require ( "./appMsgs" )
Node 仍然會(huì)尋找appMsgs.js文件,但它也會(huì)尋找appMsgs 作為目錄 ,無論先找到哪個(gè),它都會(huì)將其拉入。
現(xiàn)在讓我們看看代碼:
我創(chuàng)建了一個(gè)文件夾, 名為記錄器 和文件夾內(nèi),我創(chuàng)建了一個(gè)文件index.js。
這是index.js文件中的代碼:
這是需要此模塊的 app.js文件:
所以,在我們的例子中,我們可以說:
JavaScript:
var logger = require ( "./logger/index.js" )
這將是完全有效的。但相反,只需說以下內(nèi)容:
JavaScript:
var logger = require ( "./logger" )
由于沒有l(wèi)ogger.js,有一個(gè) logger directory,默認(rèn)情況下它會(huì)加載index.js作為我們記錄器的起點(diǎn)。這就是我給index.js命名的原因,讓我們看看執(zhí)行這段代碼的結(jié)果是什么:
因此,就其本身而言,您可能會(huì)想,為什么要費(fèi)心進(jìn)行創(chuàng)建文件夾和 inex.js 的額外步驟?
原因是您可能將一個(gè)復(fù)雜的依賴放在一起,而這個(gè)依賴可能有它所依賴的其他部分。需要記錄器的調(diào)用者不需要知道有一堆這些其他依賴項(xiàng)。
這是一種封裝形式,因此當(dāng)我們構(gòu)建更復(fù)雜的部分時(shí),我們可以從多個(gè)文件中構(gòu)建它們。然后在消費(fèi)者端,使用單個(gè)文件。它只是暗示文件夾是管理這些依賴項(xiàng)的好方法。
節(jié)點(diǎn)包管理器 (NPM)
我們還想簡(jiǎn)要討論的另一件事是 NPM。您可能已經(jīng)知道它的用途。這帶來了額外的功能,它的使用非常簡(jiǎn)單。
我們可以使用npm安裝依賴項(xiàng):
npm install underscore;
然后可以簡(jiǎn)單地在app.js 中使用它,如下所示:
你可以看到我們?nèi)绾问褂孟聞澗€包提供的功能。此外,當(dāng)我們需要這個(gè)模塊時(shí),我們沒有指定文件路徑,我們只是使用它的名稱,Nodejs 將從您應(yīng)用程序的node_modules文件夾中加載這個(gè)模塊。
這是執(zhí)行的輸出:
概括
在這篇文章中,我們學(xué)習(xí)了 Nodejs 如何管理其依賴項(xiàng),并且我們看到了在我們的應(yīng)用程序中使用的一些模式。您可以從此Git 存儲(chǔ)庫下載源代碼。如果您有任何問題或意見,請(qǐng)告訴我。直到下一次,快樂編碼!