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 才改。

Java在20年前就解决这个问题了,然后后面抄的语言没有一个完全抄对的

参考资料

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

为什么 npm 要为每个项目单独安装一遍 node_modules?的更多相关文章

  1. vue项目中安装cnpm和node_modules

    1.安装cnpm的nodejs包管理工具,命令行: npm install -g cnpm --registry=https://registry.npm.taobao.org   2. 每个vue项 ...

  2. 发布自己的npm包、开源项目

    背景:由于最近在做项目之余想做一些其他的事,所以东找找西找找的,最后决定写一个封装一些常用原型方法的NPM包,但不仅限于此.话不多说,说一下实践过程. 一.注册NPM及如何上传NPM包参考连接:htt ...

  3. npm在项目目录安装插件需要使用sudo

    今天使用node的npm安装插件的时候遇到一个问题,那就是在项目目录里面安装插件的时候,必须使用超级用户(sudo)执行才会安装成功,否则会报如下错误: 以安装 gulp-uglify 为例 $ np ...

  4. idea创建vue项目,Terminal安装npm的淘宝镜像:'npm' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    原因: 安装node.js时,不是默认路径安装,环境变量找不到npm,需要改环境变量配置: 原下: 找到安装node.js的安装路径: 改后: 成功: npm i -g cnpm --registry ...

  5. 实用的开源百度云分享爬虫项目yunshare - 安装篇

    今天开源了一个百度云网盘爬虫项目,地址是https://github.com/callmelanmao/yunshare. 百度云分享爬虫项目 github上有好几个这样的开源项目,但是都只提供了爬虫 ...

  6. 在React旧项目中安装并使用TypeScript的实践

    前言 本篇文章默认您大概了解什么是TypeScript,主要讲解如何在React旧项目中安装并使用TypeScript. 写这个的目的主要是网上关于TypeScript这块的讲解虽然很多,但都是一些语 ...

  7. npm run dev启动项目,electron提示throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')

    npm run dev 项目,提示 throw new Error('Electron failed to install correctly, please delete node_modules/ ...

  8. 浅谈Excel开发:八 Excel 项目的安装部署

    前面几篇文章讲解了Excel开发的几个比较主要的也是比较重要的方面,比如菜单系统,Excel对象模型,自定义函数,RTD函数,异步自定义函数,用户自定义任务面板等,在实际开发中我们还会遇到各种“千奇百 ...

  9. SpreadJS使用进阶指南 - 使用 NPM 管理你的项目

    前言 SpreadJS作为一款性能出众的纯前端电子表格控件,自2015年发布以来,已经被广泛应用于各领域“在线Excel”数据管理项目中.NPM,作为管理Node.js库最有力的手段,解决了很多Nod ...

随机推荐

  1. 从零开始学习PYTHON3讲义(八)列表类型跟冒泡排序

    <从零开始PYTHON3>第八讲 ​前面我们见过了不少的小程序,也见过了不少不同类型的变量使用的方法.但目前我们涉及到的,还都是单个的变量和单个的立即数.以变量来说,目前我们见到的,基本都 ...

  2. vue keep-alive 实现详情返回列表保留页面数据

    实现功能 详情页返回列表页,列表页保留上次浏览位置 其它页面进入到列表表,列表页刷新 当详情页有数据改变时,列表页也要更新该条数据 实现思路 用keep-alive保留列表页面数据 activated ...

  3. linux中文件的三种time(atime,mtime,ctime)

    linux下文件有3个时间的,分别是atime,mtime,ctime.有些博友对这3个时间还是比较迷茫和困惑的,我整理了下,写下来希望对博友们有所帮助. 1 这三个time的含义 简名 全名 中文名 ...

  4. 痞子衡嵌入式:语音处理工具Jays-PySPEECH诞生记(3)- 音频显示实现(Matplotlib, NumPy1.15.0)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是语音处理工具Jays-PySPEECH诞生之音频显示实现. 音频显示是Jays-PySPEECH的主要功能,Jays-PySPEECH借 ...

  5. java web 项目打包(war 包)并部署

    1.在eclipse中右键单击项目,然后Export选择WAR file,生成项目的WAR文件.具体步骤请看图片详细操作步骤: 2.把生成的WAR文件放到tomcat解压之后的webapps文件夹下. ...

  6. 用户在浏览器中输入一个url发生的奥秘

    在HTTP 客户端向服务器发送报文之前,需要用网际协议(Internet Protocol,IP)地址和端口号在客户端和服务器之间建立一条TCP/IP 连接. http://207.200.83.29 ...

  7. nginx基础

    常见的能够提供web服务的程序有apache.IIS,nginx等,LLS是windows系统中的,nginx和apache是linux系统中的,nginx是一款高性能的http和反向代理的服务器. ...

  8. C# 如何隐藏或显示工作表中的网格线

    我们知道Excel中有许多虚线形式的网格线,它们用于区分Excel工作表中的单元格.有了网格线,读者可以轻松地查看和核对工作表中的数据.Excel工作表中,网格线是默认存在的,但我们可以根据自身的需求 ...

  9. Java开发笔记(四十六)类的构造方法

    前面介绍了如何定义一个简单的类,以及它的成员属性和成员方法,从示例代码可以看到,不管是OrangeSimple还是OrangeMember,都要先利用关键字new创建一个实例,然后才能通过实例名称访问 ...

  10. BIM与GIS

    BIM行业是建筑与IT结合而形成的一个新兴行业,既然能说是行业,说明它包含的内容非常丰富,懂一点和完全懂是两码事,就好像一滴水和一片大海的范围一样.现在国内有很多高校开设了BIM专业,并对口招收了学生 ...