为什么 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那样)。
依赖管理是每个现代语言的标配。依赖管理和打包工具是两个概念,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
转载于:https://www.cnblogs.com/weiyinfu/p/8471407.html
为什么 npm 要为每个项目单独安装一遍 node_modules?相关推荐
- cmd命令 - vue项目:单独安装vue-router
cmd命令 - vue项目:单独安装vue-router 今天做测试的时候,发现之前的vue项目忘记安装vue-router 为了让项目能重新跑起来,只能另外安装一下vue-router 这里,总结一 ...
- 初识 npm script : 用 npm init 快速创建项目
初识 npm script 首先介绍创建 package.json 文件的科学方法,目标是掌握 npm init 命令.然后,通过在终端中运行自动生成的 test 命令,详细讲解 npm 脚本基本执行 ...
- webpack 的基本使用—— 创建列表隔行变色项目||在项目中安装和配置 webpack
创建列表隔行变色项目 ① 新建项目空白目录,并运行 npm init –y 命令,初始化包管理配置文件 package.json ② 新建 src 源代码目录 ③ 新建 src -> index ...
- vant部署_详解VUE项目中安装和使用vant组件
Vant 是有赞前端团队基于有赞统一的规范实现的 Vue 组件库,提供了一整套 UI 基础组件和业务组件. 特性 50+ 个经过有赞线上业务检验的组件 单元测试覆盖率超过 90% 完善的中英文文档和示 ...
- npm、cnpm、yarn的安装与常用命令
1.安装 npm curl -L https://www.npmjs.com/install.sh | sh a.临时使用(例如安装express) npm --registry https://re ...
- npm工具运行Vue项目
检查npm管理包:npm -v npm集成在node中的 安装Vue:npm install vue 安装vue-cli:npm install -g vue-cli 初始化项目:vue init w ...
- 手把手建项目 PrimeNG安装使用
手把手建项目 PrimeNG安装使用 之前写过一片关于PrimeNG的安装使用,当时也是接触不久,最近重新使用的时候发现还是有一些东西没有说清楚. 当时用的是Angular2现在已经是Angular4 ...
- VUE项目中安装和使用vant组件
Vant 是有赞前端团队基于有赞统一的规范实现的 Vue 组件库,提供了一整套 UI 基础组件和业务组件. 特性 50+ 个经过有赞线上业务检验的组件 单元测试覆盖率超过 90% 完善的中英文文档和示 ...
- npm run serve起项目报错node-sass not find
npm run serve起项目报错node-sass not find node-sass是开发中比较常见的依赖包,也是最常见见到的报错之一. 由于node-sass与别的依赖包不一样.而node- ...
最新文章
- 【 Vivado 】Performing System-Level Design Entry(总览)
- Presto实现原理和美团的使用实践
- Scrapy框架的学习(11.scrapy框架中的下载中间件的使用(DownloaderMiddlewares))
- EasyRTSPClient:基于live555封装的支持重连的RTSP客户端RTSPClient
- 初学者在python下使用Ta-lib库时遇到的一些问题及解决办法
- 《Python编程从入门到实践》记录之将Python函数存储在模块中(import、import*)
- html一个div调用的一个php页面,打开一个HTML文件,一个div/iframe中内PHP
- Apache Struts 和 Spring 开源漏洞状况的对比
- 如何用递归处理一个数组中的数据成为一个树结构_Spark处理的一些业务场景(持续更新ing)...
- SWF播放器object DEMO
- Onvif协议:IPC客户端开发之图像抓拍
- 自由软件运动与GNU项目
- ArcCatalog中通过ArcSDE向Oracle数据库中导入数据
- Arnold阿诺德电影级渲染器完全教学
- UINO优锘:深度|扒一扒图化资源申请之三生三世那点事儿
- 如何修复vagrant up失败错VBoxManage: error: The machine is already locked for a session (or being unlocked)
- Go微服务架构实战 中篇:6. 微服务治理策略
- 69的人因为穷不谈恋爱,这届年轻人脱单太难了
- CornerNet,CenterNet关键代码解读: kp,_decode,left pooling
- SSH协议原理和实践
热门文章
- 数据库设计需要注意什么
- 由System.getProperty(user.dir)引发的联想
- robotium(及百度cafe)运行testcase之后程序挂起没有响应的原因调查及解决
- SecureCRT无法使用root账户远程连接ubuntu
- 垂涎欲滴!30个美味的食品类移动应用程序【下篇】
- 怎样才能做好技术团队管理
- visual studio 2008 intellisense does not work
- 【Java从0到架构师】git 入门和基本应用
- 【matplotlib笔记】3D图像绘制
- 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT) C++ 版