JavaScript 高级深入浅出:几种主流的包管理工具

2,269 阅读8分钟

介绍

本文是 JavaScript 高级深入浅出的第 21 篇,介绍了几种主流的包管理工具

正文

1. 代码共享方案

通过模块化开发,代码可以分为多个小的结构,在以后的开发中我们就可以通过模块化的方式来封装自己的代码,并且封装为一个工具。

通过模块化,我们可以让别人使用现成的解决方案,可以帮助到全世界的程序员。那么现在的问题在于,我们该如何共享自己的代码。

那么你肯定会想到,直接放在代码托管平台,例如 Github、Gitee,那么拉取就会变得很方便。但是这种方式的弊端在哪?升级会非常麻烦,版本控制会非常麻烦,依赖管理会非常麻烦。

方式二,使用一个专门的工具来管理依赖。

  • 通过工具将代码发布到线上托管
  • 其他人可以通过工具来下载、升级、删除我们发布的代码

显然,方式二肯定是要比方式一要更加方便的。

2. 包管理工具 npm

包管理工具 npm:

  • Node Package Manager,也叫做 Node 包管理工具
  • 但是目前不仅仅是 Node 的包管理工具了,在前端项目中我们也可以通过 npm 来管理依赖
  • 例如 vue、react、koa、axios、babel、webpack、vite 等

使用 npm 需要确保自己的电脑安装了 Node,在 Node 安装过程中会自动安装 npm

npm 依赖查找地址:npmjs.com/

当我们推送一个包时,推送到了 npm 的 registry,下载这个包也是从 registry 下载的

2.1 npm 配置文件

当我们在初始化一个项目的时候,可以使用以下命令来生成一个配置文件(根目录会出现 package.json )。在配置文件中,会说明该项目依赖的包、版本、名称、描述等等。

npm init -y  # -y 表示选项默认为 yes,路径出现中文会报错

以下是配置文件中常见的属性:

  • name:项目名称【必填】

  • version:项目版本【必填】

  • description:项目描述信息

  • author:项目作者(发布的时候用)

  • license:开源协议(发布的时候用)

  • private:项目是否是私有的,当值为 true 时,不可以将该项目发布出去

  • main:项目的入口文件,比如使用 import axios from 'axios',就是从 main 属性查找文件的

  • script:用于配置一些脚本命令,可以通过 npm run xxx 来执行这个命令

    • 常用的 startteststoprestart 在运行时不需要写 run,例如:npm start
  • dependencies:放无论是生产环境还是开发环境都需要的依赖

  • devDependencies:放只有开发环境需要的依赖

  • peerDependencies:还有一种依赖关系叫做对等依赖,比如你需要的一个包是需要一个宿主依赖的,例如 ElementPlus 必须依赖 Vue3

  • engines:用于指定 Node 和 npm 的版本,在安装过程中,首先会检测对应的版本,如果不是就会报错

    • 也可以执行所在的操作系统 "os": ["darwin", "linux"],只是很少用到
  • browserlist:用于配置打包后的浏览器的兼容情况参考,这个属性相当于是给一些打包工具所服务的

2.2 依赖的版本管理

我们会发现安装的依赖版本会是这样的 ^2.0.3~2.0.3 ,这是什么意思呢?

npm 的包需要遵从 semver 版本规范

semver 版本规范为 X.Y.Z

  • X 主版本号(major):当你做了不向下兼容的 API 修改,主版本号需要加 1 位
  • Y 次版本号(minor):当你做了向下兼容的功能性新增,次版本号需要加 1 位
  • Z 修订号(patch):当你做了向下兼容的问题修正,修订号需要加 1 位
  • 次版本号改变,修订号重置为 0;主版本号改变,次版本号和修订号重置为 0

^~ 的区别:

  • ^:主版本号保持不变,次版本号和修订号安装最新版本
  • ~:主版本号和次版本号保持不变,修订号安装最新版本

package-lock.json 里面记录的是每个依赖安装的实际的版本

2.3 安装包

安装 npm 包分为两种情况:

  • 全局安装(global install):npm install @vue/cli -g
  • 局部安装(local install):npm install vue

npm install 可以被简写为 npm i ,安装的依赖会存放在 node_modules 文件夹中。

全局安装

全局安装的包会安装在系统环境变量中的NODE_PATH文件夹中,一般我们在全局安装的都是一些工具包,如 vue、webpack 等项目需要的依赖还是要安装在项目中。

局部安装

# 默认 --save 依赖放进 dependencies
npm i vue
# -D 也就是 --save-dev,依赖放进 devDependencies
npm i webpack -D

2.4 npm install 原理

我们知道使用 npm install 指令可以安装一个依赖,但是他背后的原理是什么呢?

  • 执行 npm install 后内部帮助我们做了什么操作?
  • package-lock.json 又会有什么作用?
  • 从 npm5 开始,npm 支持缓存策略,缓存有什么用呢?

npminstall.png

解析:

在 npm install 时,需要确定是否有 package-lock.json

  • 有 lock 文件
    • 检测 lock 包中的版本是否和 package.json 中的一致(会根据 semver 版本规范检测)
      • 如果不一致,就重新构建依赖关系,走顶层的流程
    • 一致的情况下,有限去找缓存
      • 没有找到,会从 registry 中下载,走顶层的流程
    • 找到缓存,获取缓存中的压缩文件,解压到 node_modules 中
  • 没有 lock 文件
    • 分析依赖关系,这是因为我们下载的依赖可能也依赖了其他包
    • 从 registry 中下载包(如果设置了镜像,会从镜像服务器中下载)
    • 获取压缩包后对压缩包进行缓存(从 npm5 开始有的)
    • 将压缩包解压到项目的 node_modules 中

2.5 package-lock.json

以当前 LTS 版本 V8 版本为例

{
  "name": "test",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "dependencies": {
    "axios": {
      "version": "0.26.0",
      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.0.tgz",
      "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
      "requires": {
        "follow-redirects": "^1.14.8"
      }
    },
    "follow-redirects": {
      "version": "1.14.9",
      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
      "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
    }
  },
  "packages": {}
}
  • name:项目名称
  • version:项目版本
  • lockfileVersion:lock 文件版本
  • requires:使用 requires 来追踪模块的依赖关系
  • dependencies:项目的依赖
    • version:依赖的实际版本
    • resolved:记录下载的位置,也就是 registry 的位置
    • requires:记录当前模块的依赖
    • integrity:用于从缓存中获取索引,再通过索引获取压缩包文件
  • packages:包的实际位置映射

具体的属性说明请参考 这里

2.6 npm 常见命令

卸载包

npm uninstall package -g
npm uninstall package -D
npm uninstall package

强制重新构建

npm rebuild

清除缓存

npm cache clean

查看更多命令

3. 包管理工具 yarn

yarn 是由 Facebook、Google、Exponent、Tilde 联合推出的 JS 包管理工具,主要是为了弥补 npm 早期的缺陷(如依赖管理混乱、下载速度慢等等)而诞生的。

以下为 npm 与 yarn 的对比

NpmYarn
npm installyarn install
npm install [package]yarn add [package]
npm install --save [package]yarn add [package]
npm install --save-dev [package]yarn add [package] [--dev/-D]
npm rebuildyarn install --force
npm uninstall [package]yarn remove [package]
npm uninstall --save-dev [package]yarn remove [package]
npm uninstall --save-optional [package]yarn remove [package]
npm cache cleanyarn cache clean
rm -rn node_modules && npm installyarn upgrade

yarn 和 npm 不能混用,这是因为 yarn 也有自己的 lock 文件叫做 yarn.lock

4. 包管理工具 cnpm

cnpm 用于解决国内无法正常从 registry.npmjs.org/ 下载包的问题

可以通过 npm config get registry 来查看 registry 的下载地址

使用以下命令来设置国内镜像:

npm config set registry==https://registry.npmmirror.com

也可以来使用此国内镜像深度定制的包管理工具 cnpm

查看这里 获取更多 cnpm 的相关信息

但是要注意:

  • 国内镜像并不是实时与 npm registry 更新(据官方说是 10 分钟同步一次)
  • 不保证未来国内镜像是否仍然维护

所以一种推荐用法是:

  • npm 的 registry 指向官方
  • cnpm 的 registry 指向国内镜像

5. 包管理工具 pnpm

pnpm 则是一种新生代的包管理工具,这里是官方文档

为什么我们要使用 pnpm 而不是 yarn 呢?

  • pnpm 可以节省磁盘空间
  • pnpm 的下载速度更快
  • pnpm 不会压平依赖关系树(node_modules 的嵌套关系不会很深)
  • 很多大型项目的包管理工具也都切换成了 pnpm,例如 Vue

目前,pnpm 是非常推荐使用的。

另外,pnpm 也有锁文件 pnpm-lock.yaml

点击这里 查看更多使用 pnpm 的使用方法

6. npx

npx 随着 Node 的安装自动安装

npx 是 npm 在 5.2 版本之后自带的一个命令

  • npx 的作用非常多,但是比较常见的命令是调用项目中的某个模块的指令

当我们想要使用一个工具时(例如 pnpm),我们想要在命令行中调用 pnpm,就必须要全局安装这个包。那我们该如何调用安装在项目中的某个包的指令呢?

可以在 package.json 的 scripts 中加入

方式一:直接找到文件执行:

./node_modules/.bin/webpack --version

方式二:使用 npm script 执行

{
    "scripts": {
        "webpack": "webpack --version"
    }
}
# 运行 script 优先找 local
npm run webpack

方式三:直接通过 npx 执行

# 或者直接使用 npx
npx webpack

7. 发布自己的包

在发布包的时候要注意一点,package.json 中的 name、version、description、keyword 都是对应在 npmjs.com 上的

package.json 中有一个属性 repository,可以填写这个包对应的 url 地址

{
    "repository": {
        "type": "git",
        "url": "your-git-repo-url"
    }
}

7.1 登录

需要在命令行登入 npm

npm login

登陆成功后,命令行会出现这个信息

Logged in as your-username on https://registry.npmjs.org/.

7.2 发布

发布前将自己的 package.json 修改为合规的版本

使用以下命令发布自己的包

npm publish

7.3 更新包

  • 修改版本号(符合 semver 规范)
  • 重新发布

总结

本文介绍了目前主流的几种包管理工具,以及一些细节,希望会对你有所帮助