其實也不用每次都安裝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那樣)。
依賴管理是每個現代語言的標配。依賴管理和打包工具是兩個概念,npm是依賴管理,webpack是打包工具。
在Java中,maven既能實現依賴管理又能實現打包。
何為依賴管理?
依賴管理說白了就是構建一個有向無環圖。項目A依賴項目B,項目B依賴項目C,那么當你的項目依賴A的時候,依賴管理工具會自動讓你的項目依賴B和C。
要想構建有向無環圖,最關鍵的是要將項目轉化為有向無環圖中的結點。所以對於項目往往有description,作者信息,版本信息等額外信息。
依賴管理最難解決的問題就是版本問題。庫A依賴庫B,庫C也依賴庫B,但是庫A跟庫C所依賴的庫B不是同一版本,如果庫B的這兩個版本兼容還好,如果不兼容就坑大發了,這是無解的問題。
下面說說Java,Python,Node三種語言中的依賴管理。
- Java中的Maven倉庫在開發者電腦上是全局的,所有項目的依賴都集中存放在本地倉庫中。每個項目都有pom.xml指明依賴本地倉庫中的哪些庫。
- Python中的pip跟maven很像,在開發者電腦上也是集中存放包,但是它不存在版本問題。也就是說,在你的電腦上每個python庫都只有一個版本。既然如此,當你依賴某個庫的時候,就無需指明版本號,直接引用包的名稱就可以了。
- Node中的依賴如果你不寫package.json,那么依賴的就是全局的庫;如果寫了package.json,就會把所有依賴下載到node_modules文件夾。
Node這種node_modules文件夾的方式有利有弊。
最明顯的壞處是:
- 每次都需要安裝依賴,費流量,網速慢時很費時間
- 浪費磁盤空間,每個node_modules中包含的工具很多,動輒20M
最明顯的好處是:
- 使用package.json安裝好之后,node_modules文件夾中沒有版本信息,從而package.json可以刪掉了。
移動/復制/打包項目比較簡單,對於開發、部署都有好處 - 對於設計npm的人來說,這是最省事的包依賴方法。這就好比maven安裝依賴之后自動將jar包安裝到項目的lib里面。
- 隨意改代碼。安裝在node_modules里面的東西,你可以隨便改,無需擔心對其它項目的影響。在Java中使用maven管理項目時,如果想要定制某個庫,就需要更改這個庫的源代碼,這時就需要把這個庫的源代碼復制到項目中,跟node_modules是一個道理。npm的設計者大概認為:前端都是經常修改庫的源代碼的。
我認為不同語言對於依賴的定位不同。Java中的庫是嚴謹的庫,Python中的庫是玩具一樣、隨手寫就的庫,Node里的庫是代碼片段一樣的庫。Node里面的庫既然定位就是代碼片段,那么當然要將代碼片段跟你的項目放在一起了,這樣才方便你修改這些代碼片段。可是隨着時間推移,node中的庫越來越大、越來越嚴謹,這種對待代碼片段的方式就有些不好了。
總結:這是一種設計,這種設計有利有弊。
以下是知乎上的回答片段:
全局依賴的唯一好處就是省了硬盤空間。這種省毫無意義。首先如果你要為幾十幾百兆的硬盤空間斤斤計較,那么也許你已經窮得不適合做開發。其次如果需要支持全局多版本也省不了多少。至於有人說的,每次npm install時間太長,我認為這也不是個事。npm install又不是天天搞,而且只是第一次全新checkout的時候比較慢,以后都是增量更新。實在嫌慢(比如因為防火牆的原因),可以把node_modules一起提交到git里去。
其實我覺得完全可以做成全局的,依賴模塊都裝到公共目錄,每個項目在 npm install 時用符號連接把每個模塊對應的版本目錄連過來,或者干脆就在 require() 時去全局的模塊目錄里去找,這樣也不麻煩。實際上我團隊就包了這樣一個命令,安裝時是全局安裝,項目 init 時符號連接過來,很省時間和空間。但 npm 沒有這么做,我覺得一是在一開始沒考慮到,后面也就不好改了。實際上就連 node_modules 模塊多層嵌套導致路徑過長的問題,也是一開始設計時沒考慮周全,到了 npm3 才改。