本文拜读百度@小蘑菇哥哥的Node.js 中的依赖管理,正文从这里开始~
papackage.json
nodeJs项目中都会有package.json的存在,这个文件会记录运行该项目所有依赖,并且以平级的形式展示出来,文件内容与下图类似:
但是在实际中,一个npm包往往会依赖于其他几个甚至几十个包,这些被额外依赖的包是不会记录在项目的package.json中,只会记录在node_modules安装包下的package.json文件中,由于node_modules对于所有的依赖都是并行存放,这样会导致依赖过多不好管理。
papackage-lock.json
package-lock.json 内部记录的是每一个依赖的实际安装信息,例如名字,安装的版本号,安装的地址 (npm registry 上的 tar 包地址)等等。额外的,它会把依赖的依赖也记录起来,因此整个文件是一个树形结构,保存依赖嵌套关系。一个简单的例子如下:
{
\"name\": \"my-lib\",
\"version\": \"1.0.0\",
\"lockfileVersion\": 1,
\"requires\": true,
\"dependencies\": {
\"array-union\": {
\"version\": \"1.0.2\",
\"resolved\": \"http://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz\",
\"integrity\": \"sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=\",
\"dev\": true,
\"requires\": {
\"array-uniq\": \"^1.0.1\"
}
}
}
}
在执行 npm i 的时候,如果发现根目录下只有 package.json 存在(这通常发生在刚创建项目时),就按照它的记录逐层递归安装依赖,并生成一个 package-lock.json 文件。如果发现根目录下两者皆有(这通常发生在开发同事把项目 checkout 到本地之后),则 npm 会比较两者。如果两者所示含义不同,则以 package.json 为准,并更新 package-lock.json;否则就直接按 package-lock 所示的版本号安装。
它存在的意义主要有 4 点:
- 1、在团队开发中,确保每个团队成员安装的依赖版本是一致的。否则因为依赖版本不一致导致的效果差异,一般很难查出来。
- 2、通常 node_modules 目录都不会提交到代码库,因此要回溯到某一天的状态是不可能的。但现在 node_modules 目录和 package.json 以及 package-lock.json 是一一对应的。所以如果开发者想回退到之前某一天的目录状态,只要把这两个文件回退到那一天的状态,再 npm i 就行了。
- 3、因为 package-lock.json 已经足以描述 node_modules 的大概信息(尤其是深层嵌套依赖),所以通过这个文件就可以查阅某个依赖包是被谁依赖进来的,而不用去翻 node_modules 目录(事实上现在目录结构打平而非嵌套,翻也翻不出来了)
- 4、在安装过程中,npm 内部会检查 node_modules 目录中已有的依赖包,并和 package-lock.json 进行比较。如果重复,则跳过安装,能大大优化安装时间。
npm 官网建议:把 package-lock.json 一起提交到代码库中,不要 ignore。但是在执行 npm publish 的时候,它会被忽略而不会发布出去。