一行代码锁定包管理器

1,692 阅读3分钟

欢迎大家参与若川大佬组织的源码共读活动: # 每周一起学习200行源码共读活动

本章节是看源码时的一些思考和总结。

场景

在我们平时和小伙伴协同开发时,新加入的小伙伴可能会使用与大家不同的包管理器install脚手架。比如团队使用的yarn,新加入的伙伴习惯了npm,但是在运行npm install的时候可能会因为依赖的缘故出现报错。特别是在进行开源项目的时候,经常会有新加入的成员询问怎么install异常。于是乎,统一包管理器就显得很有必要了。

vue3是怎么做的

在查看vue3源码时,在根目录的package.json中可以找到这个脚本


"script": {
    "preinstall": "node ./scripts/preinstall.js",
}

npm 脚本有prepost两个钩子。并且默认提供了preinstall,也就是会在install之前执行这个脚本。了解更多可以查看#阮一峰 npm scripts 使用指南

跟着这条脚本可以找到preinstall.js文件。如果本地仓库中的vue-next版本比较低,可能是锁定的yarn而非pnpm,具体以官方仓库为准。

// vue-next/scripts/preinstall.js
if (!/pnpm/.test(process.env.npm_execpath || '')) {
  console.warn(
    `\u001b[33mThis repository requires using pnpm as the package manager ` +
      ` for scripts to work properly.\u001b[39m\n`
  )
  process.exit(1) // exit非0则中止脚本
}

这样其实已经可以确定当前仓库允许的包管理器了,如果此时执行yarn或者npm安装依赖,则会报错

image.png

only-allow

但是为了方便在各个项目中使用,可以使用only-allow,它是pnpm提供的用于锁定管理器的包。在官方文档上就能找到,pnpm文档only-allow github

直接使用

{
  "scripts": {
    "preinstall": "npx only-allow pnpm"
  }
}

源码理解

源码可以查看若川提供的版本。源码不多,比较重要的是which-pm-runs包的使用。它可以获取到当前执行脚本的包管理器版本

如下图所示:

image.png

process.argv

process.argv可以获取到当前脚本,也就是package.jsonpreinstall钩子的参数,第一个参数是node,第二个参数是文件,第三个就是参数,也就是我们在package.json中设置node bin.js pnpm中的pnpm。这里的作用就是确定当前需要锁定pnpm为包管理器。

which-pm-runs

再说说which-pm-runs。作用就是确定当前安装依赖时使用的包管理器是什么。也就是如果使用yarn add xxx那么这里就是获取到yarn,如果是npm则是npm。实现的原理也很简单,大家可以自行试试,只需要以下几行代码即可

// 执行 yarn add xxx,查看日志输出
let userAgent = process.env.npm_config_user_agent
console.log(userAgent) // yarn/1.22.10 npm/? node/v14.16.1 win32 x64
const pmSpec = userAgent.split(' ')[0]
console.log(pmSpec) // yarn/1.22.10 这里就获取到了包管理器和版本

进行调试,变量输出在左边可以查看 image.png

这样,运行时使用的包管理器,需要锁定的包管理器都能获取到了,之后进行if else判断即可。 这里就不再展示了。感兴趣可以自行去了解。

参考

从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器

pnpm

only-allow-pnpm

which-pm-runs

阮一峰 npm scripts 使用指南

阮一峰 process 使用指南