作者:大志前端
鏈接:https://juejin.cn/post/6844903470797946887
來源:掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。
前言
本系列文章是根據(jù)Mosh大佬的視頻教程全方位Node開發(fā) - Mosh整理而成,個人覺得視頻非常不錯,所以計劃邊學習邊整理成文章方便后期回顧。該視頻教程是英文的,但是有中文字幕,感謝marking1212提供的中文字幕翻譯。
本篇文章大綱
- NPM介紹
- package.json
- 安裝一個包
- 使用一個包
- 包的依賴
- NPM的包與源代碼管理
- 語義化版本控制
- 列出已安裝的包
NPM介紹
NPM全稱Node Package Manager,即包管理工具。它基本是一個命令行工具,也是第三方庫注冊到Node的注冊機。
無論你想向Node添加什么功能,很可能在注冊庫中已經(jīng)第三方的免費模塊或包了。
我們打開NPM官網(wǎng)npmjs.com,NPM中的所有模塊都是免費并且可復用的。你可以很簡單的向你的應用添加這些功能模塊,同樣的,如果你在Node上有個好點子的實現(xiàn),并希望分享給大家,你可以創(chuàng)建自己的模塊,并在NPM上發(fā)布。向我們的應用添加NPM的方法,是借助一個也叫npm的命令行工具,也就是node packets manager。
所以第一件事就是打開控制臺,運行npm -v,查看我們電腦安裝的npm是什么版本,npm是伴隨著Node而來的,如果你安裝了Node也同時安裝了npm。有趣的是如果你運行node -v,你會發(fā)現(xiàn)npm的版本和node的版本是不一樣的,因為這兩個應用程序是各自獨立開發(fā)的。
有可能我們安裝的npm版本跟作者的不一樣,可以使用npm i -g npm@5.5.1來安裝指定的版本號。如果你使用的是Mac,需要前置sudo關鍵字,即sudo npm i -g npm@5.5.1,因為有可能你沒有設置好用戶權限,當你運行時可能得到一個權限錯誤,因為你要全局安裝,所以解決辦法就是前置sudo關鍵字,這只是針對Mac用戶。如果你在Window下得到權限報錯,你只能在用戶管理的地方添加用戶權限。
package.json
我們創(chuàng)建一個新的文件夾叫npm-demo,然后進入這個文件夾,在你添加任何包之前,你需要創(chuàng)建一個文件,就是package.json,這個文件本質上是一個JSON文件,它包含了你的應用或程序最基本的信息,比如名字、版本、作者、反饋的地址、依賴的關系等等,所有的Node的應用都有這個JSON文件。
為了創(chuàng)建這個文件,我們運行
npm init
復制代碼
這是一個向導式的一步步創(chuàng)建的過程,它會問你一些問題,比如第一個就是包的名稱,根據(jù)提示來按enter一直下一步即可。
我們來看下最后生成的package.json文件
{
"name": "npm-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
復制代碼
還有一個更快的創(chuàng)建的方式,之前我們用的npm init,然后你需要回答它提出的所有問題,如果你不想回答,可以立一個flag,就是--yes,這樣就能使用所有的默認值創(chuàng)建該文件。
npm init --yes
復制代碼
安裝一個包
我們先試試安裝一個很有名的包underscore,先打開npmjs.com,搜索underscore,在搜索結果中找到underscore,點擊進去,可以看到當前最新的版本和其他的一些基本信息,比如作者、Github倉庫的地址等等。
安裝方式
npm i underscore
復制代碼
回到控制臺,我們輸入npm i underscore,當運行完這行命令,發(fā)生了兩件事,首先在package.json可以看到一個新的dependencies屬性,在它下面就是underscore,在應用的package.json文件中標識了每個依賴庫的名字和版本。
看下現(xiàn)在的package.json文件
{
"name": "npm-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"underscore": "^1.9.2"
}
}
復制代碼
當我們運行了npm i,npm會從注冊庫中下載給定名稱的庫的最新版,然后會將它保存在一個叫node_modules的文件夾中,在里面你可以看到一個叫underscore的文件夾,里面有一些文件,其中一個就是package.json,每個node模塊都有的自己的package.json,就像node應用本身。
如果你打開underscore的package.json文件你就可以看見它的版本號和其他很多的基本信息,比如主頁、關鍵字等等。
在之前版本的npm,安裝包的方法是這樣的,輸入npm i underscore,后面還要附加--save的flag,沒有這個參數(shù),node的package.json中的依賴關鍵字就不會添加underscore,這個行為特征在新版的npm中改變了,不用在刻意添加--save參數(shù)了,只需要運行安裝命令npm i,安裝給定名稱的包,npm就會下載最新的版本,并且修改package.json文件,最終保存于node_modules文件夾中。
使用一個包
我們已經(jīng)安裝了underscore的第三方庫,現(xiàn)在我們來使用看看。
回到VSC,我們新建一個文件,命名為index.js,我們使用require函數(shù)來導入這個模塊。
var _ = require('underscore')
復制代碼
這就是require函數(shù)的用法,當你這里傳入了模塊名,首先它認為你需要一個核心模塊,在node中沒有一個叫underscore的核心模塊,然后require函數(shù)就會認為,也許有叫這個名字的文件或文件夾,但是之前我們說過,當你要引用文件夾中的文件,需要使用./,所以如果參數(shù)是./underscore,這樣require函數(shù)就會認為,在同一個文件夾中有一個叫underscore.js的文件,如果不是,它就會認為有一個叫underscore的文件夾,里面有一個index.js的文件,但是在我們的項目中,并沒有一個underscore的文件夾,這樣require函數(shù)就會假設第三種可能,它會認為在node_modules文件夾中有個叫underscore的庫,這就是require函數(shù)查找一個模塊的過程。
現(xiàn)在我們已經(jīng)導入underscore模塊了,我們來開始使用它,首先我們打開它的官網(wǎng)underscorejs.org,你就能看到underscore庫的文檔,這個庫包含了非常多的工具函數(shù),這里我們演示一下contains函數(shù)。
點擊文檔左側菜單的contains函數(shù),可以看到它的用法underscorejs.org/#contains。它需要兩個參數(shù),第一個參數(shù)是一個數(shù)組,第二個參數(shù)是需要在數(shù)組中搜索的特定值,結果返回的是一個布爾值。
var _ = require('underscore');
var result = _.contains([1, 2, 3], 2);
console.log(result); // true
復制代碼
我們得到的結果為true,這就是在node中使用第三方庫的方法。
包的依賴
這里我們先來做一個小練習,我們安裝一個node模塊名為mongoose,我們用它來向MangoDB保存數(shù)據(jù),這個會在后面的課程介紹。
我們先來安裝一下
npm i mongoose
復制代碼
安裝完,打開package.json,可以看到這個文件已經(jīng)更新了,dependencies中多了一個mongoose的屬性,現(xiàn)在我們再來看下node_modules文件夾有什么變化。
回到VSC,點開node_modules文件夾,發(fā)現(xiàn)多出了很多文件夾,這些是從哪里來的,我們只是安裝了一個mongoose模塊而已,如下圖:
<figcaption></figcaption>
這里你看到的這些庫,是其他的node模塊包,并且是mongoose模塊依賴的庫,在之前版本的npm中,這個過程是不同的,所有第三方庫依賴的庫是安裝在自身文件夾中的。
例如這里的underscore文件夾,我假設它依賴一些其他庫,在之前版本的npm中,這些庫將存儲在這個文件夾中,在另一個叫node_modules文件夾中,這樣node模塊和它的依賴模塊是高度耦合的,這樣就一團糟了,一個庫可能被多次安裝,這樣你可能會得到一個非常深度嵌套的文件結構,特別在Window中,是限制了文件夾包含對象的數(shù)量的,所以現(xiàn)在的npm這個實現(xiàn)過程已經(jīng)不同了。
現(xiàn)在所有應用的依賴以及它們的依賴,都保存在最外層的node_modules文件夾中,也有例外,比如兩個模塊依賴同樣庫但所依賴的版本不同,這樣它們的依賴將各自保存于它們自身的文件夾中。
NPM的包與源代碼管理
我們可以看到在node_modules中有不少的文件夾,這還是非常簡單的應用,在真實的開發(fā)中,會有更多的文件夾,node_modules文件夾的大小增長的非常迅速,在實際的開發(fā)中,node_modules文件夾的大小可能有幾百兆,當在源碼控制倉庫中檢查源碼時,你不會想要包含這些文件夾的,因為每次當別人檢查你的源代碼時,都需要等待幾百兆數(shù)據(jù)的下載。
事實上當你想將代碼從一處拷到另一處,比如說你想通過email或者網(wǎng)盤發(fā)給朋友,你不想發(fā)送所有node_modules的內(nèi)容,這時候你可能會問,那這些依賴怎么辦,沒有又不行,好消息是所有依賴的信息都保存在package.json文件中,比如現(xiàn)在我們有兩個依賴庫underscore和mongoose,這樣可以輕松的將依賴庫在任何地方任何機器上恢復回來。
為了演示,我們先把node_modules文件夾刪掉,回到控制臺,我們通過npm i來恢復所有的依賴庫,npm會檢查package.json,然后會從npm注冊庫中下載所有的依賴,如你所見,node_modules文件夾又回來了,并且恢復了所有的依賴。這就是為什么我們在源碼版本控制的時候不用包含依賴庫。
如果我們使用的是Git,我們來看一下如何在Git下排除這個文件夾,回到控制臺,我們要在文件夾中生成一個Git倉庫,執(zhí)行命令
git init
復制代碼
這樣就生成了一個Git本地倉庫(前提需要你電腦已經(jīng)安裝了Git,沒有安裝的自行安裝一下)。
如果你運行git status,如你所見,下面這些是需要添加到Git倉庫的文件
<figcaption></figcaption>
我們這里需要排除node_modules文件夾,回到VSC,在文件夾的根目錄創(chuàng)建一個新文件,只需要設置擴展名是.gitignore,這個文件沒有文件名,這里面可以列出所有排除在Git倉庫之外的文件和文件夾,我們打開這個文件寫上
node_modules/
復制代碼
這里要注意加上/,表示它是一個文件夾,保存修改。
現(xiàn)在回到控制臺,再次運行git status,可以看到這里已經(jīng)不再包含node_modules文件夾了,之前還有的,現(xiàn)在已經(jīng)沒有了,取而代之的是.gitignore文件,這就是如何在Git倉庫中排除node_modules文件夾的方法。
<figcaption></figcaption>
最后我們運行git add .,并在git commit提交時留下日志信息“我的第一次提交”
git add .
git commit -m "我的第一次提交"
復制代碼
語義化版本控制
在之前的章節(jié)中,我們有提到一個冪符號^,就是package.json文件中的dependencies屬性中出現(xiàn)的版本號前面的那個符號。
"dependencies": {
"mongoose": "^5.9.0",
"underscore": "^1.9.2"
}
復制代碼
在計算機里這是插入符號,但是這里是什么意思呢?為了理解這個符號,首先要理解語義版本控制,也就是SemVer,下面簡稱SV。
SV
在SV中,node包的版本號有3個部分,比如我們看到mongoose的版本號是5.9.0,第一個數(shù)字5我們叫主要版本號,第二個9我們叫次要版本號,第三個0我們叫補丁號:它是用來表示修復的bug。
補丁號
比方說某一天,mongoose的開發(fā)者找到一個在當前版本下的bug,他們修復了錯誤并發(fā)布了新版本,那新的版本號應該是5.9.1,所以當他們修復了錯誤,他們就增加補丁號的數(shù)字。
次要版本號
次要版本號是表示添加了新特性,不會破壞現(xiàn)有的api,同樣如果是mongoose團隊添加了一個新特性,沒有破壞現(xiàn)有的接口設置,他們就會增加次要版本號的數(shù)字值,那么這個版本號應該是5.10.0,補丁號是0,是因為發(fā)布時在這個版本中還沒找到bug,所以也意味著不穩(wěn)定,當他們發(fā)現(xiàn)了bug時并且修復了錯誤,他們就會增加補丁版本號的值。
主要版本號
最后一點如果他們添加了新特性,很可能破壞了現(xiàn)有應用與mongoose的依賴關系,他們那就會增加主要版本號的數(shù)字值,這樣下一個主要版本就應該是6.0.0,這就是我們所說的語義化版本控制。
這邊的^符號
我們這邊看到的^符號,是告訴npm你關心mongoose的任何版本更新,只要主要版本號是5,如果有更新的次要版本或者補丁版本可以下載,我們就關注這個包并下載。
比如說今天當我們新建一個工程,我們使用的這個版本是5.9.0,6個月之后有人從Git倉庫中檢查代碼的時候,然后,他使用npm i來恢復源碼倉庫,就在這時正好有新版本的mongoose已經(jīng)發(fā)布了,只要它的版本是5,也就是說沒有主要更新或者重大更新,那這個新版本就會被npm i工具下載到本地的node_modules文件夾中。
另一種情況不使用^插入符號是這樣的,5.x這兩種寫法是一樣的,有時候在現(xiàn)實的開發(fā)中,有可能看到的不是插入符號^而是看到波浪線~,比如下面這樣
"dependencies": {
"mongoose": "~5.9.0"
}
復制代碼
這個意思是你對任何版本只要主要版本號是5并且次要版本號是9,另一種特別指定版本號的語法就是5.9.x,如果有新的補丁版發(fā)布,我們就下載那個新版本。
如你所見,插入符號和波浪線符號是幫助我們保持應用為最新,伴隨最新發(fā)布的依賴庫,但是有時這會造成問題,特別在現(xiàn)實開發(fā)中,例如underscore發(fā)布了一個新版本號為1.9.3,它修復了一些bug,但是也破壞了一些其他的東西,這可能意味著你應用接口出現(xiàn)故障,這種情況下你需要確保你使用的是相同的版本,如果有人在幾個月之后檢查倉庫中的代碼你需要確保它使用和第一天完全一致的underscore版本,為了做到這點,你可以簡單的刪除這個波浪線或者插入符號,這樣下一次你運行npm i就會安裝特定的版本。
"dependencies": {
"underscore": "1.9.3"
}
復制代碼
以上這些就是如何進行版本的語義化并使用正確的版本。
列出已安裝的包
現(xiàn)在你知道插入符號^的意義了,意思是你可以在本應用中使用只要主要版本號是5的任何最新版的mongoose,現(xiàn)實中當你重置你的依賴庫,有可能在node_modules中的mongoose已經(jīng)高于這個版本了。我怎么知道我已經(jīng)安裝了什么版本的庫,有兩種方法:
1、一個是查看mongoose庫下的package.json文件
打開node_modules文件夾,找到mongoose文件夾,找到package.json,滾動到最底下,可以看到有個version屬性,這就是現(xiàn)在已經(jīng)安裝的版本號,如下圖
<figcaption></figcaption>
但是這有點復雜了,如果你要查看很多個依賴,你肯定不想一個個找出package.json來查看,如果你想查看和列出所有依賴庫的版本,你可以簡單運行
npm list
復制代碼
控制臺輸出如下圖
<figcaption></figcaption>
這棵樹表示了所有的依賴和它們的依賴,例如我們正使用的underscore的1.9.2版本,同時看到mongoose和它的所有依賴,可以在名字后面看到它們對應的版本號,這棵樹有太多細節(jié)可能有點亂,也許你只對自己應用的依賴感興趣,而不是這些包自己的依賴,如果是這種情況,當運行npm list的時候,我們可以添加一個參數(shù)--depth=0,這樣可以只看到你的應用所需的依賴,這里就是mongoose和underscore,如下圖所示
<figcaption></figcaption>
好了,本篇文章先到這里。
最后
感謝您的閱讀,希望對你有所幫助。由于本人水平有限,如果文中有描述不當?shù)牡胤?,煩請指正,非常感謝。
作者:大志前端
鏈接:https://juejin.cn/post/6844903470797946887
來源:掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。