preinstall钩子

Vue3 源码用了 npm 的 preinstall 钩子 约束,只能使用 pnpm 安装依赖。
npm钩子文档

  1. // vue-next/package.json
  2. {
  3. "private": true,
  4. "version": "3.2.22",
  5. "scripts": {
  6. "preinstall": "node ./scripts/preinstall.js",
  7. }
  8. }

npm run preinstall后先运行preinstall.js,然后运行了install.js,最后是postinstall.js

preinstall.js

  1. // vue-next/scripts/preinstall.js
  2. if (!/pnpm/.test(process.env.npm_execpath || '')) {
  3. console.warn(
  4. `\u001b[33mThis repository requires using pnpm as the package manager ` +
  5. ` for scripts to work properly.\u001b[39m\n`
  6. )
  7. process.exit(1)
  8. }

process.argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是 node,第二个成员是脚本文件名,其余成员是脚本文件的参数。

  1. console.log(process.argv)
  2. /*
  3. [
  4. 'C:\\nodejs\\node.exe',
  5. 'D:\\CS\\Repositories-self\\源码共读\\only-allow-analysis\\1.js'
  6. ]
  7. */
  8. console.log(process.env)
  9. // 返回一个对象 包含本机环境的一些熟悉,全大写常量

可以在本地新建一个环境变量NODE_ENV,用它确定当前所处的开发阶段,生产阶段设为production,开发阶段设为develop或staging,然后在脚本中读取process.env.NODE_ENV即可。

  1. NODE_ENV=production node app.js

image.png

要过一会才生效console.log(process.env.NODE_ENV)

process对象

阮一峰

Only allow pnpm

只需要在package.json添加,就可以避免使用其他包管理器,使用了就报错。

  1. {
  2. "scripts": {
  3. "preinstall": "npx only-allow pnpm"
  4. }
  5. }

image.png

写一个自己的only-allow

require只能导入CJS的包,注意一些包旧版本用CJS,新版本用ESM

  1. import whichPMRuns from 'which-pm-runs'
  2. import boxen from 'boxen'
  3. const argv = process.argv.slice(2) // ['node' 'my-only-allow' 'pnpm']
  4. if (!argv.length) {
  5. console.log('please specitfy the package manager you want to use: pnpm | yarn | npm')
  6. process.exit(1)
  7. }
  8. // 想要约束的包管理器 'pnpm'
  9. const wantedPM = argv[0]
  10. if (wantedPM !== 'pnpm' && wantedPM !== 'yarn' && wantedPM !== 'npm') {
  11. console.log('Then packge manager specified is invalid , only allow pnpm | yarn | npm')
  12. process.exit(1)
  13. }
  14. // { name: 'yarn', version: '1.22.18' }
  15. const usedPM = whichPMRuns()
  16. // 输出警告
  17. if (usedPM && usedPM.name !== wantedPM) {
  18. const boxOptions = { borderColor: 'red', borderStyle: 'double', padding: 1 }
  19. switch (wantedPM) {
  20. case 'pnpm':
  21. console.log(boxen(`please use pnpm`, boxOptions))
  22. break
  23. case 'yarn':
  24. console.log(boxen(`please use yarn`, boxOptions));
  25. break
  26. case 'npm':
  27. console.log(boxen(`please use npm`, boxOptions));
  28. break
  29. }
  30. process.exit(1)
  31. }

npx

npx运行的时候,自动去node_modules/.bin路径和环境变量中里面检查命令是否存在。