【若川视野 x 源码共读】第16期 | vue3 & vite 源码中的一行代码统一团队包管理器规范

87 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。

这是源码共读的第16期,链接:juejin.cn/post/708314…

准备工作

  1. 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,第二个成员是脚本文件名,其余成员是脚本文件的参数。

  1. vite源码中使用only-allow包完成限制包管理器的功能(源码位置github

image.png 我们看到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来获取用户使用的包管理工具