源码学习目录

1. 前言

1.1 环境

  1. 操作系统: macOS 11.5.2
  2. 浏览器: Chrome 94.0.4606.81
  3. only-allow 1.0.0(2年没更新了)
  4. which-pm-runs 1.0.0(5年没更新了)

    1.2 阅读该文章可以get以下知识点

  5. 学会 npm 钩子

  6. 学会 “preinstall”: “npx only-allow pnpm” 一行代码统一规范包管理器
  7. 学到 only-allow 原理

    2. 开始

    2.1 vue的包管理器规范

    vue怎么发布这篇文章中,我们了解到是通过npm hook钩子,在install执行之前,执行了脚本检测包管理器执行路径,如果含有pnpm,才可以install,否则直接报错

    2.2 vite的包管理器规范

    1. "preinstall": "npx only-allow pnpm"
    vite通过only-allow的包去规范包管理器,这个npm包是pnpm自己发布的,而且没有安装到本地,直接通过npx从远端拉取运行

    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 ‘) process.exit(1) } // 希望的包,目前就支持npm/pnpm/yarn const wantedPM = argv[0] // 如果不在这些中,直接关闭程序 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) }

  1. <a name="zlMY9"></a>
  2. ## 2.4 which-pm-runs源码
  3. ```javascript
  4. module.exports = function () {
  5. // 判断有没有npm_config_user_agent环境变量
  6. if (!process.env.npm_config_user_agent) {
  7. return undefined
  8. }
  9. // npm_config_user_agent 的值 "pnpm/6.23.6 npm/? node/v14.18.2 darwin x64"
  10. return pmFromUserAgent(process.env.npm_config_user_agent)
  11. }
  12. function pmFromUserAgent (userAgent) {
  13. // 这里是拿到包管理工具的名称和版本pnpm/6.23.6
  14. const pmSpec = userAgent.split(' ')[0]
  15. // 找到/的位置,其实也可以用split('/')直接去拆分,感觉更方便
  16. const separatorPos = pmSpec.lastIndexOf('/')
  17. return {
  18. name: pmSpec.substr(0, separatorPos),
  19. version: pmSpec.substr(separatorPos + 1)
  20. }
  21. }

3. 总结

  1. 熟悉了process.env.npm_config_user_agent这个属性,是用来记录包管理器信息和node版本,还有操作系统和cpu架构,前提是运行了包管理器
  2. 属性npm的钩子函数preinstall
  3. npx的使用,不需要安装包依赖
  4. only-allow库的使用,来规范包管理工具

    4. 参考文档

  5. https://juejin.cn/post/7033560885050212389

  6. https://www.npmjs.com/package/only-allow
  7. https://www.npmjs.com/package/which-pm-runs