preinstall钩子
Vue3 源码用了 npm 的 preinstall 钩子 约束,只能使用 pnpm 安装依赖。
npm钩子文档
// vue-next/package.json
{
"private": true,
"version": "3.2.22",
"scripts": {
"preinstall": "node ./scripts/preinstall.js",
}
}
npm run preinstall
后先运行preinstall.js
,然后运行了install.js
,最后是postinstall.js
preinstall.js
// 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)
}
process.argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是 node,第二个成员是脚本文件名,其余成员是脚本文件的参数。
console.log(process.argv)
/*
[
'C:\\nodejs\\node.exe',
'D:\\CS\\Repositories-self\\源码共读\\only-allow-analysis\\1.js'
]
*/
console.log(process.env)
// 返回一个对象 包含本机环境的一些熟悉,全大写常量
可以在本地新建一个环境变量NODE_ENV,用它确定当前所处的开发阶段,生产阶段设为production,开发阶段设为develop或staging,然后在脚本中读取process.env.NODE_ENV即可。
NODE_ENV=production node app.js
要过一会才生效console.log(process.env.NODE_ENV)
process对象
Only allow pnpm
只需要在package.json添加,就可以避免使用其他包管理器,使用了就报错。
{
"scripts": {
"preinstall": "npx only-allow pnpm"
}
}
写一个自己的only-allow
require只能导入CJS的包,注意一些包旧版本用CJS,新版本用ESM
import whichPMRuns from 'which-pm-runs'
import boxen from 'boxen'
const argv = process.argv.slice(2) // ['node' 'my-only-allow' 'pnpm']
if (!argv.length) {
console.log('please specitfy the package manager you want to use: pnpm | yarn | npm')
process.exit(1)
}
// 想要约束的包管理器 'pnpm'
const wantedPM = argv[0]
if (wantedPM !== 'pnpm' && wantedPM !== 'yarn' && wantedPM !== 'npm') {
console.log('Then packge manager specified is invalid , only allow pnpm | yarn | npm')
process.exit(1)
}
// { name: 'yarn', version: '1.22.18' }
const usedPM = whichPMRuns()
// 输出警告
if (usedPM && usedPM.name !== wantedPM) {
const boxOptions = { borderColor: 'red', borderStyle: 'double', padding: 1 }
switch (wantedPM) {
case 'pnpm':
console.log(boxen(`please use pnpm`, boxOptions))
break
case 'yarn':
console.log(boxen(`please use yarn`, boxOptions));
break
case 'npm':
console.log(boxen(`please use npm`, boxOptions));
break
}
process.exit(1)
}
npx
npx运行的时候,自动去node_modules/.bin路径和环境变量中里面检查命令是否存在。