本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
这是源码共读的第16期,链接:juejin.cn/post/708314…
准备工作
Vue3
中限制使用包管理器的实现位置是在package.json
文件中,源码位置Vue3
{
"private": true,
"version": "3.2.22",
"scripts": {
"preinstall": "node ./scripts/preinstall.js"
}
}
查看 ./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)
}
这段代码也相对简单,校验如果不是 pnpm
执行脚本则报错,退出进程。
关于 process
对象可以查看 阮一峰老师 process 对象
process.argv
属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是 node
,第二个成员是脚本文件名,其余成员是脚本文件的参数。
vite
源码中使用only-allow
包完成限制包管理器的功能(源码位置github
)
我们看到
vite
源码中使用了only-allow
only-allow源码解析
#!/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 <npm|pnpm|yarn>')
process.exit(1)
}
// 第一个参数则是 用户传入的希望使用的包管理器
// 比如 npx only-allow pnpm
// 这里调试是 node bin.js pnpm
const wantedPM = argv[0]
// npm pnpm yarn 都不是 退出
if (
wantedPM !== 'npm'
&& wantedPM !== 'pnpm'
&& wantedPM !== 'yarn'
) {
console.log(`"${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)
}
\
跟着断点,我们可以查看到 which-pm-runs。
which-pm-runs 当前运行的是哪一个包管理器
'use strict'
module.exports = function () {
if (!process.env.npm_config_user_agent) {
return undefined
}
return pmFromUserAgent(process.env.npm_config_user_agent)
}
function pmFromUserAgent (userAgent) {
const pmSpec = userAgent.split(' ')[0]
const separatorPos = pmSpec.lastIndexOf('/')
return {
name: pmSpec.substr(0, separatorPos),
version: pmSpec.substr(separatorPos + 1)
}
}
根据源码可以知道主要是根据 npm_config_user_agent
来获取用户使用的包管理工具