作者:京东零售 陈震

在前端工程化中,JavaScript 依赖包管理是非常重要的一环。依赖包通常是项目所依赖的第三方库、工具和框架等资源,它们能够帮助我们减少重复开发、提高效率并且确保项目可以正确的运行。

目前比较常见的前端包管理器有 npm 和 Yarn,npm 是 Node.js 自带的包管理器,它可以安装、共享和分发 node.js 模块。最近pnpm也挺火的,通过并行下载和安装依赖项,在执行安装、更新、删除等操作时也更快。

但无论使用哪个包管理器,都要通过 package.json 文件的版本控制功能,保证在不同开发环境中的一致性。那么,package.json是如何进行依赖包管理的呢?我们来一起深入了解一下package.json的配置方式。

一、分类管理



根据package.json规范,依赖包被大致分为以下几种:dependencies、devDependencies、optionalDependencies、peerDependencies和bundledDependencies总共5种。dependencies和devDependencies这两项是我们使用较为频繁的。

1、dependencies

工程在生产环境下也需要使用的依赖,例如react、antd等,使用npm安装插件时,会默认写入dependencies,也可以使用-P或--save-prod后缀。

2、devDependencies

工程只有开发环境需要,生产环境不需要的依赖,例如eslint、babel等,使用-D或--save-dev来写入devDependencies。

3、optionalDependencies

顾名思义,依赖是可选的,它们只有在运行时需要使用某些功能时才会被引入。通常用于实现某些可选的功能或优化。例如,一个包可能依赖于某个库来实现某种高级功能,但是这个库在某些环境下不存在或不可用。在这种情况下,可以将该库声明为可选依赖项,并在代码中检查该依赖项是否存在,然后根据情况来决定是否使用该高级功能。使用这个功能的工程比较少,使用-O或--save-optional来写入optionalDependencies。

4、peerDependencies

工程需要和这个依赖配套使用,一般用于解决插件依赖的核心库的版本和主项目依赖的核心库的版本不一致的问题,常见于开发配套插件。例如vuex@4.1.0声明了:

"peerDependencies": {
"vue": "^3.2.0"
}

表明vuex@4.1.0需要和vue@^ 3.2.0一起安装和使用,否则可能会出现异常。使用-O或--save-optional来写入optionalDependencies。

5、bundledDependencies

工程依赖于某些特定的依赖项,并且希望在运行时不必再次下载它们,则可以使用该选项。npm pack会将这些依赖一同放入生成的包中,并且在npm install时本工程,这些依赖项也会被一同安装。使用-B或--save-bundle来写入bundledDependencies。

看到这里你可能会有点疑问,为什么npm没有提供类似--save-peer的指令来写入peerDependencies呢?原因是peerDependencies暗示本工程将会被其他主模块使用,但是主模块本身并不需要在项目代码中显式使用。因此官方没有支持这一指令。

二、版本管理

一般情况下,以上依赖配置(除了bundledDependencies)都需要指定依赖的版本号,版本号遵循semver语义化版本规范(Semantic Versioning)命名规则,可以用下图表示,如2.1.0、3.1.4-beta.2等。

  • 当发生不兼容的 API 修改时,更新major位
  • 当做了向下兼容的功能性新增时,更新minor位
  • 当做了向下兼容的问题修正时,更新patch位

可选的-tags即先行版本号,可以作为发布正式版之前的版本,格式是在修订版本号后面加上一个连接号(-),再加上一连串以点(.)分割的标识符,标识符可以由英文、数字和连接号([0-9A-Za-z-])组成。

在 npm 的依赖的规则中,还有~、>、<、=、>=、<=、-、||、x、X、*等符号来描述适用的版本范围;

  • ^ :表示只锁定major,不小于指定版本号的版本范围。例如^1.1.0,代表>=1.1.0 <2.0.0的版本范围。

  • ~ :表示锁定major和minor,不小于指定版本号的版本号。例如~1.1.0,代表>=1.1.0 <1.2.0的版本范围。

  • x、X、*:表示通配符。例如1.1.x,也代表>=1.1.0 <1.2.0的版本范围。

默认情况下,若指定了一个版本范围,npm会在范围内安装最新版本的依赖。当使用 npm install XX 时,会安装当前最新版本,并在版本号前默认加上 ^ 符号。因此在安装运行老项目时,很容易出现安装依赖后,项目启动报错的情况,原因就是某些依赖没有做到很好的向下兼容,导致重新安装的版本太高造成兼容性错误,此时需要定位错误依赖并回退版本。

三、npm install加载机制

npm install核心流程大致分为以下5步:

1、npm 向 registry 查询依赖压缩包的网址。
2、下载压缩包,存放在cache目录,供下次安装时使用。
3、解压压缩包到当前项目的node_modules目录。
4、把所有安装的包信息写入package-lock.json,供下次安装时使用。
5、继续处理依赖的依赖。

install的过程速度也和每一个步骤息息相关:

(1)共享工程package-lock.json,可以避免向registry查询的步骤,并且保证不同环境下安装包的一致性。

(2)使用下载速度快的registry镜像(例如jd镜像)。

(3)预先进行依赖关系分析构建依赖关系,然后最后再并行下载(例如yarn)。

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

Node工程的依赖包管理方式的更多相关文章

  1. bower一个强大的前端依赖包管理工具

    在介绍之前,你必须的知道bower是基于nodejs开发的,所以你首先必须得有个nodejs环境,至于这么安装nodejs网上一大堆教程,对了使用bower还需要安装git,这里就不多说了. #### ...

  2. go依赖包管理工具vendor基础

    go依赖包管理工具vendor基础 vendor是go的依赖包管理工具,主要用于管理项目中使用到的一些依赖. 它将项目依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的 ...

  3. python的虚拟环境管理工具venv使用方法介绍及与nodejs的包管理方式对比

    一.nodejs 包管理方式 我们知道, nodejs的包管理工具npm可以安装项目所需要的包,安装方法及区别如下: npm i module_name -g 全局安装 npm i module_na ...

  4. 【转】Mapreduce部署与第三方依赖包管理

    Mapreduce部署是总会涉及到第三方包依赖问题,这些第三方包配置的方式不同,会对mapreduce的部署便捷性有一些影响,有时候还会导致脚本出错.本文介绍几种常用的配置方式: 1. HADOOP_ ...

  5. node.js中npm包管理工具

    现在安装node.js,默认就会帮我们装上了npm包管理工具,npm主要用来下载,安装,管理第三方模块. 创建一个包描述文件: npm init [-y] 查看包的信息 npm info <pa ...

  6. Mapreduce部署与第三方依赖包管理

    Mapreduce部署是总会涉及到第三方包依赖问题,这些第三方包配置的方式不同,会对mapreduce的部署便捷性有一些影响,有时候还会导致脚本出错.本文介绍几种常用的配置方式: 1. HADOOP_ ...

  7. node.js开发 npm包管理工具

    npm介绍 说明:npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等) 使用npm安装插件:命令提示符执行npm instal ...

  8. Go依赖包管理--间接依赖

    目录 1.indirect含义 1.2 直接依赖未启用 Go module 1.2 直接依赖 go.mod 文件不完整 2.总结 1.indirect含义 在使用 Go module 过程中,随着引入 ...

  9. node.js开发 npm包管理工具 npm 和 cnpm区别

    npm 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用. 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用 np ...

  10. 难道只有我一个人想吐槽npm这种包管理方式么

    实在忍不住吐槽 说实话有强迫症的我忍了很久了,实在是忍不住写篇文章来吐槽一下. 标题可能说的有点大了,我要吐槽的是:我可能只需要某一个小小的功能模块A,结果模块A依赖B-F这5个模块,然后B又依赖这1 ...

随机推荐

  1. 记一次自定义管理工厂使用spring自动装载bean

    1.核心工厂配置类 @Componentpublic class HandlerContext { private Map<String, AbstractHandler> handler ...

  2. 字符串练习1 于是他错误的点名开始了(Trie)

    题目链接在这里:P2580 于是他错误的点名开始了 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 是一道trie树的板子题,注意理解trie树的每一个节点代表的是一个状态,这个状态 ...

  3. Google Play新功能 让您的应用在Play商店中闪耀

    Google Play 商店的商品详情内容是帮助潜在用户了解您应用的功能和价值的最佳方式.您提供的资源和信息 (应用说明.图像和视频) 对用户决定下载应用而言至关重要. 随着越来越多的用户购买移动设备 ...

  4. winform 防止奔溃重启

    static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...

  5. 不使用setTimeout的延迟执行

    function sleep(ms){ var time = new Date(); time.setTime(time.getTime() + ms); while(new Date().getTi ...

  6. gitee使用

    1.github的国内跳转 github国内无法直接访问,所以直接使用gitee导入github工程 https://gitee.com/     2.虚拟机配置ssh公钥 https://gitee ...

  7. Windows 任务栏透明 居中

    任务栏设置 任务栏居中 由于windows默认的程序是从左往右显示,看着可能有一点不舒服,当然如果使用习惯的话,忽然居中,可能更不舒服 首先搜索字符映射表 点击字符映设表中第五行的空白字符,选择进行复 ...

  8. 归一化,正则化,标准化,dropout的联系与区别

    归一化(Normalization)是指将数据缩放到一定范围内,一般是将数据映射到[0,1]或[-1,1]之间.这样可以避免不同特征的数值差异过大而导致的训练困难,同时也有助于加快梯度下降的收敛速度. ...

  9. VsCode里面在JavaWeb项目里面配置Maven环境详解

    1.在之前已经新建完成一个JavaWeb项目的基础上开始 2.设置里面搜索Maven,找到这个,然后进行定位 3.将Tomcat Server配置进去(右上角有一个加号) (对于已经学过Java的并不 ...

  10. 【Keil】浅学一下keil中的.sct文件

    [Keil]浅学一下keil中的.sct文件 最近重新捣鼓了acfly的源码,有了新的有趣发现,当然,过程并不有趣. 起因 clone下来我去年提交的代码,编译 ...... 报错辣! linking ...