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源码```javascriptmodule.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.6const 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
