当前位置: 首页 > news >正文

读懂package.json -- 依赖管理

npm做为Javascript项目的包管理工具,由于其与Node.js的紧密配合(npm和Node.js出自一人之手),目前已经基本没有竞争对手。

包管理工具要解决的主要问题就是依赖包的安装,在Javascript项目中,包的依赖关系是由package.json给出的,这篇文件将介绍package.json中描述的依赖信息。

依赖管理

在package.json中,有如下几项涉及到依赖包的描述:

  • dependencies

     项目中使用到的包,但不包括测试所使用的包
  • devDependencies

    主要是在测试时使用的包,也包括一些代码编译的包,比如将coffee-script编译为javascript。也就是说在仅仅使用该项目的时候(而不进行测试等环节),不需要安装的包可以放在devDependencies中

  • peerDependencies

    如果改项目需要指明一些有协作关系的包的版本时,使用peerDependencies。这里使用了协作,而不是依赖,是我个人的理解。peerDependencies并不是必须安装的包,但如果一旦要安装,就要符合要求。比如react-dom的package.json中有如下的描述:

    "peerDependencies": {
        "react": "^15.6.1"
       },

    peerDependencies至少打消了一些顾虑,比如react生态中用到的一些包在升级的时候会不会不匹配?

  • optionalDependencies

    如果有一些依赖包即使安装失败,项目仍然能够运行或者希望npm继续运行,就可以使用optionalDependencies。另外optionalDependencies会覆盖dependencies中的同名依赖包,所以不要在两个地方都写。

  • bundledDependencies/bundleDependencies

    如果在打包发布的使用希望一些依赖包也出现在最终的包里,那么可以将包的名字放在bundledDependencies,bundledDependencies的值是一个字符串数组,如:

    "name": "awesome-web-framework",
    "version": "1.0.0",
    "bundledDependencies": [
        'renderized', 'super-streams'
       ]

    npm pack会将renderized super-streams放入生成的包awesome-web-framework-1.0.0.tgz中,并且在npm install awesome-web-framework-1.0.0.tgz时,renderized super-streams也会被一同安装。

这些项的内容形式都是一样的(除了bundledDependencies),只是作用不同,如:

  "dependencies": {
    "base62": "~0.1.1",
    "commoner": "~0.7.0",
    "esprima": "https://github.com/facebook/esprima/tarball/ca28795124d45968e62a7b4b336d23a053ac3a84",
    "recast": "~0.4.8",
    "source-map": "~0.1.22"
  }

key就是项目的名词,而value可以有多种形式

  • version,遵循semver

  • 一个tarball的url

  • 一个git url

  • 本地路径

关于semver会在另一篇文章中介绍(先挖个坑)。

依赖树

不同于很多语言的依赖管理,npm使用的是依赖树。也就是说每个依赖包会有一套自己指定的(在package.json中说明的)依赖包,而不会和其他包共享。
例如,mod-a依赖mod-b@1.0.0,mod-c依赖mod-b@2.0.0,而现在有一个项目依赖mod-a和mod-c,那么最终安装的依赖包如下:

├─┬ node_modules
│ ├─┬ mod-a
│ │ ├── mod-b@1.0.0
│ ├─┬ mod-c
│ │ ├── mod-b@2.0.0

而Node.js在加载依赖包的时候会处理这个问题。之所以文章最开始说npm和Node.js的紧密合作也是这个原因。

使用依赖树来管理包带来了一个明显的好处,不用处理依赖冲突的问题。这个问题在早期的Java项目中比较常见,而在使用了Maven和Gradle之后,情况有所缓解,但只能减轻同一个包多个版本被放入发布的包中这种情况,仍然无法解决依赖冲突这个根本问题。

依赖树也有一些缺点:

  • 代码量增加。由于不能共享相同的包(在npm v3中,尝试着共享相同版本的库,但还是比较弱),导致最终打包的时候有同一个库的多个版本的代码出现在最终包中。

  • 潜在的运行时冲突。以上面的例子为例,可能有些时候,mod-b的两个版本无法同时运行,而这只有在运行或者测试的时候才能被发现。

希望以上的介绍能够帮助你更好的理解npm的依赖管理。

相关文章:

  • Spring AOP 之一:基本概念与流程
  • TheGreastOpenSourceSoftware
  • Android系统在新进程中启动自定义服务过程(startService)的原理分析 (下)
  • Codeforces Round #419 (Div. 2) A-E
  • Ubuntu下输入sudo时如何不用输入密码?
  • 认识多渲染目标(Multiple Render Targets)技术
  • 说说參数传递(泛型托付)
  • 【转】Python常用文件操作参考
  • 在spring-boot工程中添加spring mvc拦截器
  • nodejs读写大文件
  • TreeView 控件应用
  • 终端代码重复率检测实践
  • 恋爱男女冷笑话
  • kali之***XP系统3(非法关闭计算机)
  • startActivityForResult的疑问与探索
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Android 控件背景颜色处理
  • exif信息对照
  • JavaScript学习总结——原型
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • ViewService——一种保证客户端与服务端同步的方法
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 首页查询功能的一次实现过程
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 1.Ext JS 建立web开发工程
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • Prometheus VS InfluxDB
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​iOS实时查看App运行日志
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #NOIP 2014# day.1 T2 联合权值
  • #QT(智能家居界面-界面切换)
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (145)光线追踪距离场柔和阴影
  • (ibm)Java 语言的 XPath API
  • (二)学习JVM —— 垃圾回收机制
  • (分类)KNN算法- 参数调优
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (蓝桥杯每日一题)love
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (四)JPA - JQPL 实现增删改查
  • (五)Python 垃圾回收机制
  • .bashrc在哪里,alias妙用
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET Standard 的管理策略
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET处理HTTP请求
  • .Net的C#语言取月份数值对应的MonthName值
  • [ vulhub漏洞复现篇 ] GhostScript 沙箱绕过(任意命令执行)漏洞CVE-2019-6116
  • [BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法