沒想到你是這樣的npm install

大家好,我是若川。今天給大家推薦一篇關于 npm install 的好文。很快能看完。

點擊下方卡片關注我、加個星標
學習源碼整體架構系列、年度總結、JS基礎系列


前言

項目中執行npm install發生了什么,眾所周知,執行npm install時會在當前項目目錄的node_modules中安裝依賴。并且將依賴項的層級關系保存在package-lock.json中。那么依賴項的層級關系是怎么確認的?依賴項之間是否存在區別?有無package-lock.json在安裝時有什么區別呢?筆者希望借以此文可以和讀者們一起厘清npm install

工欲善其事必先利其器,先一起來了解下npm install

npm-install

常用的命令包含(具體含義和執行效果會在下文說明)

  • npm install

  • npm install -P|--save-prod

  • npm install -D|--save-dev

  • npm install -O|--save-optional

  • npm install --no-save

aliases: npm i, npm add

npm install這個命令會在項目路徑下安裝一個或多個依賴包,如果項目中存在package-locknpm-shrinkwrapyarn.lock文件。那么安裝過程將就基于這些文件。其優先級為:

  • npm-shrinkwrap.json

  • package-lock.json

  • yarn.lock

其中npm-shrinkwrap.jsonnpm 5之前的依賴鎖定文件,其在npm 5后被package-lock.json替換。兩個文件功能類似,最大的不同是npm-shrinkwrap.json需要執行npm shrinkwrap來初始化生成,而package-lock.json為自動生成。本文撰寫時npm使用的版本為v6.14.5,故下文所有樣例均在此版本下做交流討論。其他版本任何問題歡迎留言討論。yarn.lockyarn cli的產物,不在此文章討論。

npm install執行時會解析package.json中定義的依賴關系,進而根據package.json生成package-lock.json依賴鎖定文件。package.json中的依賴關系可以由開發人員自行定義,也可使用npm install [--optional]來指定存儲位置,或使用npm install --no-save不進行存儲。

自古習物先習源。package.json中是那些在影響依賴樹呢?

package.json

package.json文件是項目的描述文件,包括項目的nameversiondescription等很多字段。但真正影響依賴樹的并不多,包括dependenciesdevDependenciespeerDependenciesoptionalDependenciesbundledDependencies。下面一起來看下他們區別和使用場景。

dependencies:主要依賴

dependencies是主要依賴。也即必須依賴。由包名和版本區間映射成的簡單 json對象組成。版本區間由一個或多個分隔符組成。是項目運行、打包的主要依賴。執行npm install時會從上至下遞歸安裝dependencies及其內部依賴。并將解析的依賴樹存儲在package-lock.json中。會隨版本一起發布到npm庫。是最重要的依賴節點。

執行npm install -P|--save-prod會將指定包放入此節點。

常用的dependencies如:axiosfetch等。

{"dependencies":?{"axios":?"^0.21.1","fetch":?"^1.1.0"}
}

devDependencies:開發依賴

devDependencies是開發環境的依賴。其格式同dependencies,開發人員本地執行npm install時也會從上至下遞歸安裝devDependencies及其內部依賴。并將解析的依賴樹存儲在package-lock.json中。也會隨版本一起發布到npm庫。但是不同的是。非開發人員通過項目安裝依賴時。也就是包安裝后出現在node_modules中時,devDependencies不會被安裝,也不會出現在項目的package-lock.json中。

所以在開發時,dependenciesdevDependencies區別并不大,但是作為依賴包被其他項目引入時,只有dependencies中的依賴會被解析成依賴樹并下載。devDependencies中的依賴會被忽略。

執行npm install -D|--save-dev會將指定包放入此節點。

常用的devDependencies如:karmamochawebpack

{"devDependencies":?{"karma":?"^1.3.0","mocha":?"^5.2.0","webpack":?"^1.13.1","webpack-dev-server":?"^1.14.1"}
}

peerDependencies:同等依賴

peerDependencies是同等依賴。其格式同dependencies。主要在開發包時使用,常規開發項目不建議使用。比如某些情況下開發人員為了表明在不同系統和運行環境下的兼容性,即非所有情況下都是必要的依賴。就會通過peerDependencies來表明。peerDependencies中更像是當前包所依賴是插件。peerDependencies里面的依賴會隨版本一起發布,但是不會自動安裝,需要開發和使用人員手動安裝。(npm v7下會默認安裝)

eslint-plugin-prettier會同等依賴eslintprettier。即eslint-plugin-prettier需要在eslintprettier都安裝時才會生效。但是其自身并不會強制安裝eslintprettier。而是會通過警告的方式提示開發者。

`eslint-plugin-prettier requires a peer of xxx but none is installed. You must install peer dependencies yourself`

如果不想在未安裝peerDependencies的情況下提示警告。可以通過peerDependenciesMeta設置optionaltrue來關閉警告。

{"peerDependencies":?{"eslint":?">=5.0.0","prettier":?">=1.13.0"},"peerDependenciesMeta":?{"eslint":?{"optional":?true}}
}

optionalDependencies:可選依賴

optionalDependencies是可選依賴。其格式同dependencies。當需要某些依賴在安裝失敗時不會阻塞項目的運行和打包,就可以使用optionalDependencies來定義。optionalDependencies里面的依賴會隨版本一起發布,且會自動安裝。可以使用npm install --no-optional命令來跳過安裝。

執行npm install -O|--save-optional會將指定包放入此節點。

optionalDependencies使用需要開發者在項目中作兼容。如:

try?{var?foo?=?require('foo')var?fooVersion?=?require('foo/package.json').version
}?catch?(er)?{foo?=?null
}if?(?notGoodFooVersion(fooVersion)?)?{foo?=?null
}//?..?then?later?in?your?program?..if?(foo)?{foo.doFooThings()
}

bundledDependencies:綁定依賴

bundledDependencies是綁定依賴,其值是一個數組。在發包時定義綁定包。常規項目中使用的并不多。和npm install的也并無關系,所以在此不做過多介紹。值得一提的是,使用bundleDependencies也是可以的。

{"name":?"awesome-web-framework","version":?"1.0.0","bundledDependencies":?["renderized","super-streams"]
}

了解了package.json中影響依賴樹的節點,那么接下來就是重頭戲npm install登場了~

一、無依賴沖突

最簡單的場景莫過于此,當項目的package.json的依賴及其子 依賴間沒有沖突時,即A依賴B、C、D。表示為A[B、C、D]。則依賴會平鋪在node_modules下。即使有多個相同的依賴,只要版本不存在沖突,就都符合當前場景。

舉個例子。fetch-demo2項目中值依賴fetch這一個包。

{"name":?"fetch-demo2","version":?"1.0.0","description":?"","main":?"index.js","dependencies":?{"fetch":?"^1.1.0"},"devDependencies":?{},"scripts":?{"test":?"echo?\"Error:?no?test?specified\"?&&?exit?1"},"keywords":?[],"author":?"","license":?"ISC"
}

此時執行npm i,會得到如下的目錄結構的node_modules

可得到依賴樹(根據package-lock.json分析得出)

不難得出以下結論。當項目中的依賴無沖突時,項目依賴及其內部依賴會平鋪在一級node_modules中。

二、項目頂級依賴存在沖突

頂級依賴即項目package.json中的依賴。

當項目頂級依賴存在沖突時,會將頂級依賴放在node_modules中的一級目錄下,沖突的包放在自己的node_modules下。為了模擬這種場景,將biskviit@2.0.0放在fetch-demo2項目的頂級依賴上。

{"dependencies":?{"fetch":?"^1.1.0","biskviit":?"2.0.0"}
}

執行npm install后查看node_modules的目錄結構

分析依賴樹

可以看出在頂級依賴biskviit@2.0.0和內部依賴biskviit@1.0.1存在沖突時,頂級依賴會占據node_modules的一級目錄,內部依賴則會存儲在其內部的node_modules

三、項目內部依賴存在沖突

當項目的內部依賴存在沖突時,會先檢測一級node_modules是否存在依賴包,不存在則存儲,如果存在判斷是否有版本沖突,無沖突則使用一級node_modules的依賴包,有沖突則存儲在自身的node_modules中。還是舉例說明下。

一級node_modules無沖突包

發布自定義新包conflict-lbywer@1.0.0npm。其依賴為

{"dependencies":?{"biskviit":?"^2.0.0"}
}

fetch-demo2項目的頂級依賴改為

{"dependencies":?{"conflict-lbywer":?"1.0.0","fetch":?"^1.1.0"}
}

刪除node_modulespackage-lock.json后,執行npm i后,查看目錄結構

分析依賴樹

可以看出conflict-lbywer所依賴的biskviit@2.0.0fetch所依賴的biskviit@1.0.1沖突時,在頂級依賴沒有biskviit的情況下,將biskviit@2.0.0安裝到了頂級依賴。

如果將頂級依賴中的conflict-lbywerfetch更換順序呢,依賴包順序是否會發生變化,我們一起來研究。

修改頂級依賴

{"dependencies":?{"fetch":?"^1.1.0","conflict-lbywer":?"1.0.0"}
}

刪除node_modulespackage-lock.json后,執行npm i后,查看目錄結構

分析依賴樹

可以看出在調整conflict-lbywerfetch順序后,目錄結構并無變化。所以可得出結論,在一級node_modules不存在沖突包時,會將高版本的包放在一級node_modules中。低版本的放到內部的node_modules中。

一級node_modules有沖突包

如果一級node_modules有沖突包時,情況又會如何呢?

刪除頂級依賴中的conflict-lbywer

{"dependencies":?{"fetch":?"^1.1.0"}
}

刪除node_modulespackage-lock.json后,執行npm i后,查看目錄結構

分析依賴樹

頂級依賴添加conflict-lbywer@1.0.0

{"dependencies":?{"fetch":?"^1.1.0","conflict-lbywer":?"1.0.0"}
}

直接執行npm i后,查看目錄結構

分析依賴樹

可以發現,在依賴樹無變化的情況下,node_modules的目錄結構是不一樣的。所以可以得出結論,在一級node_moudles已經存在依賴包的情況下,新安裝的依賴包如果存在沖突,會安裝到內部的node_modules中。

四、存在package-lock.json

這種情況也很簡單,npm install會完全按照package-lock.josn的層級結構下載安裝依賴包

刪除node_moudles后,執行npm install

直接執行npm install后,查看目錄結構

分析依賴樹

可以發現,在存在package-lock.json的情況下,node_modules的目錄結構是穩定的。

結語

上文對執行npm install時,一些常見的情況做了測試和分析,也給出了相應的結論。歡迎讀者們批評斧正。也歡迎打賞點贊哦~

參考文獻和鏈接

  • https://docs.npmjs.com/cli/v7/commands/npm-install

  • https://docs.npmjs.com/cli/v7/configuring-npm/package-json

  • https://docs.npmjs.com/cli/v7/configuring-npm/folders


最近組建了一個江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你進群。


今日話題

略。歡迎分享、收藏、點贊、在看我的公眾號文章~

一個愿景是幫助5年內前端人走向前列的公眾號

可加我個人微信?ruochuan12,長期交流學習

推薦閱讀

我在阿里招前端,我該怎么幫你(可進模擬面試群)

2年前端經驗,做的項目沒技術含量,怎么辦?

點擊方卡片關注我、加個星標

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》多篇,在知乎、掘金收獲超百萬閱讀。

從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。

同時,活躍在知乎@若川,掘金@若川。致力于分享前端開發經驗,愿景:幫助5年內前端人走向前列。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275798.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Django——Model

一、 ORM 在 MVC 或者說 MTV 設計模式中,模型(M)代表對數據庫的操作。那么如何操作數據庫呢? 我們可以在 Python 代碼中嵌入 SQL 語句。 但是問題又來了,Python 怎么連接數據庫呢?可以使用類似 pymysql 這一…

大理石在哪兒_如何創建用戶體驗寫作課程而又不失大理石

大理石在哪兒I’m a UX Writer. It’s a designated human on the software development team who writes words for interfaces. All the words. From the tiniest tooltips to navigation, to buttons, to errors, and so on, ad infinitum. UX writing is less writing and …

理解 JavaScript 閉包

簡介 Closure 所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。 閉包是 ECMAScript (JavaScript)最強大的特性之一,但…

in the java search_elasticsearch which: no java in (/sbin:/bin:/usr/sbin:/usr/bin)

機器:centos7.2javahome:export JAVA_HOME/root/jdk1.8.0_60export PATH$JAVA_HOME/bin:$PATHexport CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar[rooti-j73a8nn6 ~]# java -versionjava version “1.8.0_60”Java(TM) SE Runtime Envir…

Vuex 源碼還有一些缺陷?

我看了vuex3和vuex4的源碼也輸出了文章,看到這篇時,vuex還有缺陷?看了看確實是好文,不愧是大佬寫的。文章不算長,推薦給大家看看。點擊下方卡片關注我、加個星標學習源碼整體架構系列、年度總結、JS基礎系列眾所周知&a…

三級菜單頁面布局_三級菜單的最快導航布局

三級菜單頁面布局重點 (Top highlight)When users navigate an interface, there’s a need for speed. The faster it is for them to find what they’re looking for, the more time they’ll save on their task.用戶導航界面時,需要提高速度。 他們找到所需內容…

java contains 通配符_java刪除文件支持通配符

packagecom.covics.zfh;importjava.io.File;importjava.io.FilenameFilter;/*** 實現帶*號的刪除文件*authordoudou**/public classTestDeleteFile {public static voidmain(String args[]) {boolean delFile //windows//deleteFileWithSign("E:\\fileDeleteTest\\test\\t…

「線性基」學習小結

向量空間 向量空間亦稱線性空間。 形式化的,我們定義一個向量空間\((P,V,,\cdot)\) 其中 \(P\)是一個域,\(V\)是一個非空的集合,其中的集合稱作向量,同時定義兩種運算分別為向量加法和標量乘法 一個\(P\)上的向量空間\((P,V,,\cdo…

ux體驗網站 英國_定義網站圖像時的UX注意事項

ux體驗網站 英國As the saying goes —俗話說 - “A picture is worth a thousand words.”“一張圖片勝過千言萬語。” When creating content on the web, it’s often recommended to be using high-quality imageries and making sure that the images serve its purpose …

iconfont 支持全新的彩色字體圖標

大家好,我是若川。iconfont我相信大家都用過,而現在支持全新的彩色字體圖標了。這是第二次轉載,上一次的好文是2020 前端技術發展回顧。點擊下方卡片關注我、加個星標學習源碼整體架構系列、年度總結、JS基礎系列一直以來,Web 中想…

回文算法java實現_java算法題:最長回文串

LeetCode: 給定一個包含大寫字母和小寫字母的字符串,找到通過這些字母構造成的最長的回文串。在構造過程中,請注意區分大小寫。比如"Aa"不能當做一個回文字符串。注 意:假設字符串的長度不會超過 1010。思路:利用hashset&#xff0…

Spring校驗@RequestParams和@PathVariables參數

我們在寫Rest API接口時候會用到很多的RequestParam和PathVariable進行參數的傳遞,但是在校驗的時候,不像使用RequestBody那樣的直接寫在實體類中,我們這篇文章講解一下如何去校驗這些參數。 依賴配置 要使用Java Validation API,…

出色的社區網站_《最后的我們》中出色的制作系統

出色的社區網站游戲設計分析 (GAME DESIGN ANALYSIS) The Last of Us became an instant classic the day it was released, back in 2013. At the sunset of the sixth console generation, it felt like Naughty Dog managed to raise the bar in all critical areas of game…

入坑 Electron 開發跨平臺桌面應用

?作為一個跨平臺的桌面應用開發框架,Electron 的迷人之處在于,它是建立在 Chromium 和 Node.js 之上的 —— 二位分工明確,一個負責界面,一個負責背后的邏輯,典型的「你負責貌美如花,我負責賺錢養家」。上…

Google 拼音會導致卡 Ctrl 鍵?

如果你使用 Windows 7 系統,并同時安裝了 Google 輸入法,那么 Firefox 啟動時、WoW 時一定也常遇到卡住 Ctrl 鍵的問題。 今天仔細搜索了下,傳說將輸入法中“Ctrl鍵快速定位”關閉即可,有待驗證,先記錄著…轉載于:http…

java 接口編程_JAVA面向接口編程

一、什么是面向接口編程要正確地使用Java語言進行面向對象的編程,從而提高程序的復用性,增加程序的可維護性、可擴展性,就必須是面向接口的編程。面向接口的編程就意味著:開發系統時,主體構架使用接口,接口…

不僅僅是手機,MWC現全球首例 5G NR 商用部署

近日,MWC大會在在巴塞羅那舉行,5G折疊手機和5G部署進度成為這屆大會的重點。除了華為與三星發布的折疊手機外,本屆大會另一個值得關注的要點是三星和賽靈思宣布推進5G NR 商用部署在韓國落地,這應該是全球首例 5G 新無線電 (NR) 商…

小程序 顯示細線_精心設計:高密度顯示器上的細線

小程序 顯示細線Despite the many benefits of Retina displays, there is one clear drawback that must be considered when designing for high-density screens:盡管Retina顯示器具有許多優點,但在設計高密度屏幕時仍必須考慮一個明顯的缺點: 必須避…

React 入門手冊

大家好,我是若川。推薦這篇可收藏的React入門手冊。也推薦之前一篇類似的文章《如何使用 React 和 React Hooks 創建一個天氣應用》。點擊下方卡片關注我、加個星標React 是目前為止最受歡迎的 JavaScript 框架之一,而且我相信它也是目前最好用的開發工具…

函數04 - 零基礎入門學習C語言35

第七章:函數04 讓編程改變世界 Change the world by program 上節課的練習簡單講解,給力!! 1.自己實現pow()函數并嘗試驗證…… 2.猜想下sqrt()函數的原理并嘗試編程……(暫時只要求整型數據) 3.編寫一個用來統…