likes
comments
collection
share

【源码学习】 第⑨期 | 团队成员npm、yarn、pnpm混用?教你一行代码规范包管理器

作者站长头像
站长
· 阅读数 27

前言

    好的作品背后都通常有好的团队支撑,并且在日常开发中难免会遇到团队协作的问题。正所谓无规矩不成方圆,想要团队快速高效完成进度,必要的代码规范少不了,如果你的团队成员也混用npm、yarn、pnpm,那就快来学学一行代码规范包管理器吧~

收获清单

  • npm命令钩子
  • 一行代码规范包管理器
  • 调试源码
  • only-allow原理

调试准备

1.npm脚本命令钩子
npm install 顺序
    1.  `preinstall`
    2.  `install`
    3.  `postinstall`

更多npm命令钩子也可以参照 npm docs

2.一行代码规范包管理器实现

    仔细看过vite源码的小伙伴应该不会陌生下面这个命令,vite的 package.json就有下面这个命令,如果只是关注实现的小伙伴其实看到这里就可以了,但我们的宗旨是知其然才能知其所以然,从命令可以看出这行代码主要依靠only-allow包实现,关键only-allow包源码只有40行左右,下面就让我们正式进入调试代码准备吧~

{
  "scripts": {
    "preinstall": "npx only-allow pnpm"
  }
}
3.下载only-allow源码
git clone https://github.com/pnpm/only-allow.git
cd only-allow
# npm i -g pnpm
pnpm i

代码调试

1. 养成调试前先看使用说明书 README.md 的好习惯

【源码学习】 第⑨期 | 团队成员npm、yarn、pnpm混用?教你一行代码规范包管理器

2.从package.json找主文件入口

【源码学习】 第⑨期 | 团队成员npm、yarn、pnpm混用?教你一行代码规范包管理器

3.开启断点调试
//方式一:终端输入 
node bin.js pnpm
// 方式二: package.json 添加script命令,如:
"scripts": {

    "preinstall": "node bin.js pnpm"

  }

调试截图

【源码学习】 第⑨期 | 团队成员npm、yarn、pnpm混用?教你一行代码规范包管理器

源码分析

1.引入依赖
// 检测执行进程的包管理器
const whichPMRuns = require('which-pm-runs')
// 在终端中创建方框
const boxen = require('boxen')
1.1 whichPMRuns源码分析
'use strict'
module.exports = function () {

  // process.env.npm_config_user_agent 获取当前执行的是包管理器的名称和版本
  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('/')

  const name = pmSpec.substring(0, separatorPos)

  return {

    name: name === 'npminstall' ? 'cnpm' : name,

    version: pmSpec.substring(separatorPos + 1)

  }

}
2.获取用户指定的包管理器
// 获取进程参数
const argv = process.argv.slice(2)
// 没有指定包管理器,报错
if (argv.length === 0) {

  console.log('Please specify the wanted package manager: only-allow <npm|cnpm|pnpm|yarn>')

  process.exit(1)

}
// 指定包管理器
const wantedPM = argv[0]
// 指定包管理器不是npm、cnpm、pnpm、yarn,退出进程
if (wantedPM !== 'npm' && wantedPM !== 'cnpm' && wantedPM !== 'pnpm' && wantedPM !== 'yarn') {

  console.log(`"${wantedPM}" is not a valid package manager. Available package managers are: npm, cnpm, pnpm, or yarn.`)

  process.exit(1)

}
3. 根据指定包管理器执行装包命令
// 当前使用的包管理器
const usedPM = whichPMRuns()
// 当前进程的路径
const cwd = process.env.INIT_CWD || process.cwd()
// 是否已经安装依赖
const isInstalledAsDependency = cwd.includes('node_modules')
// 未安装依赖并且当前进程的包管理器与指定包管理器不一致,根据指定的包管理器弹出装包错误提示并退出进程
if (usedPM && usedPM.name !== wantedPM && !isInstalledAsDependency) {

  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 'cnpm':

      console.log(boxen('Use "cnpm 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)

}

总结

    今天动手调试了only-allow源码,并逐步分析了only-allow源码的实现,在此总结一下原理:其实就是利用node.js的process模块获取当前进程的包管理,若跟指定包管理器冲突就报错提示并退出进程,日常开发中我们也可以利用process模块获取进程信息,再执行相应的操作。only-allow整体实现算简单,使用上也比较方便,get这个技能就可以让其它人不敢乱用包管理器了~

转载自:https://juejin.cn/post/7142397455597109279
评论
请登录