是什么?

专门为 ci 环境准备的安装命令。

与 npm install 有什么不同?

  • npm ci 要求项目必须存在 lockfile 文件(package-lock.json、yarn.lock、npm-shrinkwrap.json)。
  • npm ci 完全根据 lockfile 文件按照依赖。
  • npm ci 安全根据 lockfile 文件安装,所以按照的过程不需要求解依赖满足问题、构造依赖树,过程会更加快。
  • npm ci 会一次性安装所有的依赖,不能一次安装一个。
  • npm ci 安装时, 如果 package.json 和 package-lock.json 存在冲突,会报错。
  • npm ci 永远不会改变 package.json 和 lockfile 文件。

    为什么需要 lockfile

    从 npm v5 版本开始,增加了 package-lock.json 文件。我们知道package-lock.json 文件的作用是锁定依赖安装结构目的是保证在任意机器上执行 npm install 都会得到完全相同的 node_modules 安装结果。

    为什么单一的 lockfile 不能确定唯一的依赖树

  • 不同的 npm 版本的安装算法和依赖安装策略不同

  • npm install 将根据 package.json 中的 semver-range version 更新依赖,某些依赖项自上次安装以来,可能已发布了新版本。

因此,保证能够完整准确地还原项目依赖,就是 lockfiles 出现的原因。

要不要提交 lockfiles 到仓库?

  • 开发一个应用,我建议把 package-lock.json 文件提交到代码版本仓库。这样可以保证项目组成员、运维部署成员或者 CI 系统,在执行 npm install 后,能得到完全一致的依赖安装内容。
  • 如果目标是开发一个给外部使用的库,那就要谨慎考虑了,因为库项目一般是被其他项目依赖的,在不使用 package-lock.json 的情况下,就可以复用主项目已经加载过的包,减少依赖重复和体积。
  • 如果我们开发的库依赖了一个精确版本号的模块,那么提交 lockfiles 到仓库可能会造成同一个依赖不同版本都被下载的情况。如果作为库开发者,真的有使用某个特定版本依赖的需要,一个更好的方式是定义 peerDependencies。

npm 早期使用的是 npm-shrinkwarp.json,它于 package-lock.json 最大的不同在于,npm 发布包的时候,默认是将 npm-shrinkwarp.json 一起发布的。

为什么会有 xxxDependencies?

  • dependencies 项目依赖
  • devDependencies 开发依赖
  • peerDependencies 前置依赖
  • bundleDependencies 绑定依赖
  • optionalDependencies 可选依赖

    dependencies 项目依赖

    项目依赖,这些依赖会成为线上代码的一部分。关联的 npm 被下载时,项目依赖也会被一起下载。

    devDependencies 开发依赖

    开发依赖,不会被自动下载,开发依赖只会在开发阶段和开发环境被用到,例如: webpack、babel-loader 等等。
    这里需要特别说明的是:并不是只有在 dependencies 中的模块才会被一起打包,而在 devDependencies 中的依赖一定不会被打包。实际上,依赖是否被打包,完全取决于项目里是否被引入了该模块。dependencies 和 devDependencies 在业务中更多的只是一个规范作用,我们自己的应用项目中,使用 npm install 命令安装依赖时,dependencies 和 devDependencies 内容都会被下载。

    peerDependencies 前置依赖

    不明思议,前置依赖就是当我们项目按照依赖 A 时,A 依赖了 B,所以我们同时需要 B。如果缺少了 B ,A 不能正常运行。所以这类依赖能正常运行的前提是核心依赖也要被提前安装。

    bundleDependencies 绑定依赖

    绑定依赖和 npm pack 打包命令有关,例如:
    1. {
    2. "key": "value",
    3. "name": "test_test-all",
    4. "version": "0.0.1",
    5. "description": "项目描述...",
    6. "main": "index.js",
    7. "license": "MIT",
    8. "dependencies": {
    9. "test_test-aaa": "link:../test-aaa"
    10. },
    11. "devDependencies": {
    12. "test_test-bbb": "link:../test-bbb"
    13. },
    14. "bundledDependencies": [
    15. "test_test-aaa",
    16. "test_test-bbb"
    17. ]
    18. }
    当执行 npm pack 时会生成一个压缩包,
    image.png
    压缩包中就包含 bundledDependencies 中声明的依赖。
    image.png
    业务方使用 npm install xxx.tgz 命令时,也会安装 bundledDependencies 中声明的依赖。

    要注意的是:在 bundledDependencies 中指定的依赖包,必须先在 dependencies 和 devDependencies 声明过,否则在 npm pack 阶段会进行报错。

optionalDependencies 可选依赖

可选依赖,不明思议即使按照失败,也不会影响整个按照过程。但是它会增加项目的不确定性和复杂性。所以一般很少使用。

Npm 团队最佳实践

  1. 优先使用 npm v5.4.2 版本以上的 npm 版本,目的是为了保证团队 npm 的先进性和稳定性。
  2. 项目第一次搭建时,使用 npm install 按照依赖,并提交 package.json 和 package-lock.json,不提交 node_modules。
  3. 项目其他成员首次 clone 项目是,执行一次 npm install。
  4. 项目中有需要升级的需求:
    1. 小版本使用 npm update @小版本
    2. 大版本使用 npm install @大版本
    3. 也可以手动修改 package.json,但是必须执行 npm install
    4. 升级完成之后提交 package.json 和 package-lock.json 文件。
  5. 项目中需要降级的需求:
    1. 执行 npm install @版本
    2. 降级完成之后提交 package.json 和 package-lock.json 文件
  6. 项目中有删除依赖的需求:
    1. 执行 npm uninstall xxx
    2. 验证无问题之后提交 package.json 和 package-lock.json 文件
  7. 项目中任何成员有提交 package.json 和 package-lock.json 文件的操作后,其他成员都需要拉取代码,执行 npm install 更新依赖
  8. 任何时候都不要修改 package-lock.json
  9. 如果 package-lock.json 出现冲突,建议本地删除 package-lock.json,再次拉远程的 package-lock.json 和 package.json,在执行 npm install 。