NPM
npm本來是Node.js的包管理工具,但隨著JS這幾年的蓬勃發展,現在的npm已經成了幾乎所有跟JS相關的工具和軟件包的管理工具了,並且還在不斷發展完善中。
本文從筆者的經驗,總結了npm安裝/卸載、更新、發布這幾個最主要功能的正確使用姿勢和一些小技巧,順便從官網搬來了npm3處理依賴的重大變化。
npm團隊已經發布了npm3,近期有小伙伴吐槽npm3安裝軟件包的時候很慢,一開始筆者也感覺相比npm2慢了不少,但經過了幾個版本的迭代,速度似乎又快起來了。
慢的同學是時候更新你的npm啦,而且之前安裝進度條模糊成一坨的問題也已經修復了。
npm v3.0安裝react的截圖
npm v3.8安裝react的截圖
npm提供了大量的命令,所有的命令幾乎都可以通過npm cmd [options]的方式使用。
學習一個命令行工具,最簡單直接的方式就是查看它的用戶手冊,npm提供了並不算很詳細的命令行手冊,可以通過npm -h查看(unix用戶還可以通過man npm查看,相對來說比windows詳細多了),需要某個npm命令更詳細的文檔則需要通過npm help cmd如npm help install來查看,注意不是 npm install help ,這樣將會安裝help包。
另外npm cmd -h也是一個快速查看命令可以怎麼使用和搭配哪些常用選項的方法。
說到npm就不得不說package.json,每一個npm包都必須有一個package.json文件,年輕時候的我還傻乎乎的從其他地方拷貝package.json過來然後修改,為了自動化還寫了個自動生成的腳本。
後來才發現原來npm自帶此功能,官方原廠功能更好更強大,只需要執行npm init即可,以交互方式完成package.json的創建。
如果想生成默認package.json,可以執行npm init -y,連交互式界面都不會出現。
另外需要注意,npm init的時候需要輸入用戶字段,如果還沒有設置npm用戶,需要通過npm addUser設置。
事實上,最小單位的npm包就是只包含一個package.json文件的包,這樣的話npm init就完成了一個npm包的創建。
npm install作為npm最重要的功能和最常用的功能,不用過多說明,這裡只介紹三個非常有用的選項–global,–save,–save-dev。
想必讀者肯定知道–global可以簡寫成-g,其實另外兩個選項也有簡寫形式,–save可以簡寫成-S,–save-dev可以簡寫成-D,注意大寫。
另外npm install也可以簡寫成npm i,相應的卸載命令npm uninstall可以簡寫成npm un,事實上npm的很多命令和選項在設計上都非常類似unix上的命令行功能,這裡指的是命令和選項都可以極大化地簡寫,只要在不混淆的情況下。
npm uninstall和npm install接受同樣的選項和參數。
–save的作用是在packaje.json的dependencies字段增加或者修改一個安裝包和版本號名值對,–save-dev則是修改devDependencies,這樣就不用安裝了某個包之後手動修改package.json,npm已經幫我們把包依賴和版本管理做好了。
以安裝react為例,
npm i react -S將為package.json增加
"dependencies":{
"react":"^0.14.7"
}
npm i react -D將增加
"devDependencies":{
"react":"^0.14.7"
}
假如react@15(版本號,下同)發布了,想嘗鮮的小伙伴該怎麼更新呢?
首先得知道npm上是否已經更新,npm info react可以查看到react在npm上發布過哪些版本以及最新的版本,但是內容太多,讓人眼花缭亂,配合grep會好一些。
其實我們只想知道react最新的版本,使用npm dist-tags ls react直接列出react發布過哪些tag,
> npm dist-tags ls react
0.10.0-rc1:0.10.0-rc1
0.11.0-rc1:0.11.0-rc1
latest:0.14.7
next:15.0.0-rc.1
以及這些tag目前最新是哪些版本,比如最常用的latest,也是默認tag。
next tag已經發布了react@15的第一個rc版了,嘗鮮的朋友可以試一試了。
另外一個命令npm outdated,會檢測當前安裝的所有npm包是否有更新,並列出可以更新的包,如果沒有任何輸出,那麼恭喜你,所有的包都是不需要更新的。
如果之前安裝的react版本是0.14.3,同時還安裝了[email protected],執行npm outdated會輸出
PackageCurrentWantedLatestLocation
react 0.14.30.14.70.14.7 example
redux 3.2.03.3.13.3.1 example
這種情況則說明react和redux該更新了,更新具體某個包使用npm update package_name即可,npm update則會更新所有可更新的包。
npm作為一個大倉庫,每天都有大量的新包發布上來,發布自己的包非常容易,而且幾乎零門檻,對應的發布的命令是npm publish,但前提是你需要一個npm賬號。
假設已經有賬號了,在發布之前需要使用npm login進行登錄,正式發布之前請先閱讀以下關於版本號的介紹。
npm包的版本號一般都是x.y.z的形式。
其中x表示主版本號,通常有重大改變或者達到裡程碑才改變;
y表示次要版本號,或二級版本號,在保證主體功能基本不變的情況下,如果適當增加了新功能可以更新此版本號;
z表示尾版本號或者補丁號,一些小范圍的修修補補就可以更新補丁號。
第一版本通常是0.0.1或者1.0.0,當修改了代碼,需要更新版本號重新發布到npm,不知道的小伙伴(年輕的我)肯定會手動修改package.json的version字段,而高級的玩法是直接使用npm version <update_type>命令自動搞定。
詳細用法可通過npm help version查看,這裡只介紹最常用的三種。
npm version patch=> z+1
npm version minor => y+1&& z=0
npm version major => x+1&& y=0&& z=0
三個選項分別對應三部分的版本號,每次運行命令會導致相應的版本號遞增一,同時子版本號清零。
如果npm包同時又是一個git倉庫,在運行了npm version <update_type>和npm publish之後,npm會自動給git倉庫打上一個跟當前版本號一樣的tag,對於掛在github上的npm包很有用。
上面介紹了npm包安裝/卸載、更新和發布,幾乎能滿足日常使用了,另外再搬點干貨過來。
npm3雖然慢,但解決了windows上npm包目錄太深的問題,相信使用過npm1或者npm2的都知道,node_modules太多太深了,甚至一不小心就超過windows資源管理器能處理的最長路徑長度了,聽起來有點拗口,說白了這時候復制粘貼刪除就會報錯了。
已經使用過npm3的肯定會發現,npm3將依賴模塊扁平化存放了,node_modules文件夾裡面子文件夾增多了,出現了很多沒有通過npm install安裝過的模塊。
npm3在安裝包的時候,由於每個包和包的依賴都會去計算是否需要再安裝,搜索起來確實變慢了,好在至少現在的npm3速度還是可以接受的。
按照官方文檔介紹,npm3處理模塊依賴的方式跟npm2很不一樣。
以下是從官網搬的磚
假如我們寫了個模塊App,需要安裝兩個包A@1和C@1,其中A@1依賴另一個包B@1,C@1依賴B@2,用npm2和npm3安裝之後的依賴圖分別是這樣的
npm3dependencies
npm3按照安裝順序存放依賴模塊,先安裝A@1,發現依賴模塊B@1沒有安裝過也沒有其他版本的B模塊沖突,所以B@1存放在第一級目錄,B@2為了避免和B@1的沖突,還是繼續放在C@1之下。
npm2沒什麼好說的,來什麼安裝什麼,根本不用理會公共依賴關系,依賴模塊一層一層往下存放就是了,下面重點講解npm3在這方面的改進。
現在App又需要安裝一個包D@1,D@1依賴B@2,使用npm3安裝之後,包結構將變成下面這樣
npm3dependencies-1
雖然C@1和D@1都依賴B@2,但是由於A@1先安裝,A@1依賴的B@1已經安裝到第一級目錄了,後續需要安裝的所有包B,只要版本不是1,都需要避免和B@1的沖突,所以只能像npm2一樣,安裝在相應包下面。
接著又安裝了一個E@1,依賴B@1,因為B@1已經安裝過,且不會有版本沖突,這時候就不用重復安裝B@1了,包結構會變成這樣
npm3dependencies-2
隨著App升級了,需要把A@1升級到A@2,而A@2依賴B@2,把E@1升級到E@2,E@2也依賴B@2,那麼B@1將不會再被誰依賴,npm將卸載B@1,新的包結構將變成這樣
npm3dependencies-3
可以看到出現了冗余,結果跟預期的不一樣,既然所有對B的依賴都是B@2,那麼只安裝一次就夠了。
npm在安裝包的時候沒有這麼“智能”,不過npm dedupe命令做的事就是重新計算依賴關系,然後將包結構整理得更合理。
執行一遍npm dedupe將得到
npm3dependencies-4
這才是最優且符合預期的結構,看來在每次安裝/卸載了包之後最好重新執行npm dedupe,以保證包結構是最優的。
npm3通過將依賴模塊扁平化安裝,避免了冗余又解決了windows上一大頭疼問題。