1. 前言
1.1 环境
- 操作系统: macOS 11.5.2
- 浏览器: Chrome 94.0.4606.81
- only-allow 1.0.0(2年没更新了)
-
1.2 阅读该文章可以get以下知识点
学会 npm 钩子
- 学会 “preinstall”: “npx only-allow pnpm” 一行代码统一规范包管理器
- 学到 only-allow 原理
2. 开始
2.1 vue的包管理器规范
从vue怎么发布这篇文章中,我们了解到是通过npm hook钩子,在install执行之前,执行了脚本检测包管理器执行路径,如果含有pnpm,才可以install,否则直接报错2.2 vite的包管理器规范
vite通过only-allow的包去规范包管理器,这个npm包是pnpm自己发布的,而且没有安装到本地,直接通过npx从远端拉取运行"preinstall": "npx only-allow pnpm"
2.3 only-allow源码
```javascript!/usr/bin/env node
// 检查是哪个包管理器 const whichPMRuns = require(‘which-pm-runs’) // 这个是命令行盒子样式 const boxen = require(‘boxen’)
const argv = process.argv.slice(2)
if (argv.length === 0) {
console.log(‘Please specify the wanted package manager: only-allow "${wantedPM}" is not a valid package manager. Available package managers are: npm, pnpm, or yarn.
)
process.exit(1)
}
// 目前使用的包
const usedPM = whichPMRuns()
// 如果两个名称不相等,直接打印错误的盒子
if (usedPM && usedPM.name !== wantedPM) {
const boxenOpts = { borderColor: ‘red’, borderStyle: ‘double’, padding: 1 }
switch (wantedPM) {
case ‘npm’:
console.log(boxen(‘Use “npm install” for installation in this project’, boxenOpts))
break
case ‘pnpm’:
console.log(boxen(`Use “pnpm install” for installation in this project.
If you don’t have pnpm, install it via “npm i -g pnpm”. For more details, go to https://pnpm.js.org/`, boxenOpts)) break case ‘yarn’: console.log(boxen(`Use “yarn” for installation in this project.
If you don’t have Yarn, install it via “npm i -g yarn”. For more details, go to https://yarnpkg.com/`, boxenOpts)) break } process.exit(1) }
<a name="zlMY9"></a>
## 2.4 which-pm-runs源码
```javascript
module.exports = function () {
// 判断有没有npm_config_user_agent环境变量
if (!process.env.npm_config_user_agent) {
return undefined
}
// npm_config_user_agent 的值 "pnpm/6.23.6 npm/? node/v14.18.2 darwin x64"
return pmFromUserAgent(process.env.npm_config_user_agent)
}
function pmFromUserAgent (userAgent) {
// 这里是拿到包管理工具的名称和版本pnpm/6.23.6
const pmSpec = userAgent.split(' ')[0]
// 找到/的位置,其实也可以用split('/')直接去拆分,感觉更方便
const separatorPos = pmSpec.lastIndexOf('/')
return {
name: pmSpec.substr(0, separatorPos),
version: pmSpec.substr(separatorPos + 1)
}
}
3. 总结
- 熟悉了process.env.npm_config_user_agent这个属性,是用来记录包管理器信息和node版本,还有操作系统和cpu架构,前提是运行了包管理器
- 属性npm的钩子函数preinstall
- npx的使用,不需要安装包依赖
-
4. 参考文档
- https://www.npmjs.com/package/only-allow
- https://www.npmjs.com/package/which-pm-runs