爲何 npm 要爲每一個項目單獨安裝一遍 node_modules?

其實也不用每次都安裝node_modules,直接使用軟鏈接便可:
windows 使用mklink /j node_modules %APPDATA%\Roaming\npm\node_modules
linux使用ls -s node_modules %APPDATA%\Roaming\npm\node_modules前端

nodejs中package.json中的依賴必須每一個項目都有本身的node_modules文件夾,而沒法在多個項目之間共用一套node_modules(像Java中的Maven那樣)。node

依賴管理是每一個現代語言的標配。依賴管理和打包工具是兩個概念,npm是依賴管理,webpack是打包工具。
在Java中,maven既能實現依賴管理又能實現打包。python

何爲依賴管理?
依賴管理說白了就是構建一個有向無環圖。項目A依賴項目B,項目B依賴項目C,那麼當你的項目依賴A的時候,依賴管理工具會自動讓你的項目依賴B和C。
要想構建有向無環圖,最關鍵的是要將項目轉化爲有向無環圖中的結點。因此對於項目每每有description,做者信息,版本信息等額外信息。
依賴管理最難解決的問題就是版本問題。庫A依賴庫B,庫C也依賴庫B,可是庫A跟庫C所依賴的庫B不是同一版本,若是庫B的這兩個版本兼容還好,若是不兼容就坑大發了,這是無解的問題。linux

下面說說Java,Python,Node三種語言中的依賴管理。webpack

  • Java中的Maven倉庫在開發者電腦上是全局的,全部項目的依賴都集中存放在本地倉庫中。每一個項目都有pom.xml指明依賴本地倉庫中的哪些庫。
  • Python中的pip跟maven很像,在開發者電腦上也是集中存放包,可是它不存在版本問題。也就是說,在你的電腦上每一個python庫都只有一個版本。既然如此,當你依賴某個庫的時候,就無需指明版本號,直接引用包的名稱就能夠了。
  • Node中的依賴若是你不寫package.json,那麼依賴的就是全局的庫;若是寫了package.json,就會把全部依賴下載到node_modules文件夾。

Node這種node_modules文件夾的方式有利有弊。
最明顯的壞處是:git

  • 每次都須要安裝依賴,費流量,網速慢時很費時間
  • 浪費磁盤空間,每一個node_modules中包含的工具不少,動輒20M

最明顯的好處是:web

  • 使用package.json安裝好以後,node_modules文件夾中沒有版本信息,從而package.json能夠刪掉了。
    移動/複製/打包項目比較簡單,對於開發、部署都有好處
  • 對於設計npm的人來講,這是最省事的包依賴方法。這就比如maven安裝依賴以後自動將jar包安裝到項目的lib裏面。
  • 隨意改代碼。安裝在node_modules裏面的東西,你能夠隨便改,無需擔憂對其它項目的影響。在Java中使用maven管理項目時,若是想要定製某個庫,就須要更改這個庫的源代碼,這時就須要把這個庫的源代碼複製到項目中,跟node_modules是一個道理。npm的設計者大概認爲:前端都是常常修改庫的源代碼的。

我認爲不一樣語言對於依賴的定位不一樣。Java中的庫是嚴謹的庫,Python中的庫是玩具同樣、隨手寫就的庫,Node裏的庫是代碼片斷同樣的庫。Node裏面的庫既然定位就是代碼片斷,那麼固然要將代碼片斷跟你的項目放在一塊兒了,這樣才方便你修改這些代碼片斷。但是隨着時間推移,node中的庫愈來愈大、愈來愈嚴謹,這種對待代碼片斷的方式就有些很差了。npm

總結:這是一種設計,這種設計有利有弊。json

如下是知乎上的回答片斷:windows

全局依賴的惟一好處就是省了硬盤空間。這種省毫無心義。首先若是你要爲幾十幾百兆的硬盤空間斤斤計較,那麼也許你已經窮得不適合作開發。其次若是須要支持全局多版本也省不了多少。至於有人說的,每次npm install時間太長,我認爲這也不是個事。npm install又不是每天搞,並且只是第一次全新checkout的時候比較慢,之後都是增量更新。實在嫌慢(好比由於防火牆的緣由),能夠把node_modules一塊兒提交到git裏去。
其實我以爲徹底能夠作成全局的,依賴模塊都裝到公共目錄,每一個項目在 npm install 時用符號鏈接把每一個模塊對應的版本目錄連過來,或者乾脆就在 require() 時去全局的模塊目錄裏去找,這樣也不麻煩。實際上我團隊就包了這樣一個命令,安裝時是全局安裝,項目 init 時符號鏈接過來,很省時間和空間。但 npm 沒有這麼作,我以爲一是在一開始沒考慮到,後面也就很差改了。實際上就連 node_modules 模塊多層嵌套致使路徑過長的問題,也是一開始設計時沒考慮周全,到了 npm3 才改。

Java在20年前就解決這個問題了,而後後面抄的語言沒有一個徹底抄對的

參考資料

https://www.zhihu.com/question/41409670

相關文章
相關標籤/搜索