为何 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

相关文章
相关标签/搜索