背景

现在前端包管理工具有npm、yarn、pnpm,在多人协作的项目中,大家一般会约定用其中一种工具,如果团队加入了新同学,使用其他包管理工具进行安装和提交。就有可能改变项目依赖版本,造成一些不可预见的问题。
所以我们需要一个工具,在代码层面强制规定使用哪一个包管理工具,only-allow用途便于此

npm 脚本钩子

“scripts”要为部分中定义的任何脚本创建“pre”或“post”脚本 package.json,只需创建另一个 具有匹配名称的脚本并将“pre”或“post”添加到它们的开头

  1. {
  2. "scripts": {
  3. "precompress": "{{ executes BEFORE the `compress` script }}",
  4. "compress": "{{ run command to compress files }}",
  5. "postcompress": "{{ executes AFTER `compress` script }}"
  6. }
  7. }

简单来说它的执行过程等于

  1. npm run precompress && npm run compress && npm run postcompress
  • 常用npm脚本内置钩子
    • prepublish:在打包和发布包之前运行,也可以在本地运行,npm install不带任何参数。(见下文)
    • prepare:在打包和发布包之前运行,在本地npm install不带任何参数,以及安装 git 依赖项时(见下文)。这是在之后运行prepublish,但在之前prepublishOnly。
    • publish, postpublish:在包发布后运行。
    • preinstall:在安装包之前运行
    • install, postinstall:安装包后运行。
    • preuninstall, uninstall:在卸载包之前运行。
    • postuninstall:在软件包卸载后运行。
    • preversion:在升级包版本之前运行。
    • version:在更新包版本之后运行,但在提交之前。
    • postversion:在更新包版本和提交之后运行。

      only-allow

      安装

      1. pnpm install only-allow -D

      使用

      在看umi源码中可以发现,只需要在scripts中添加preinstall钩子即可通过only-allow强制使用pnpm为当前项目的包管理工具
      1. "scripts": {
      2. "preinstall": "npx only-allow pnpm",
      3. },

      源码

      ```javascript

      !/usr/bin/env node

      // which-pm-runs返回包管理器和版本 const whichPMRuns = require(‘which-pm-runs’) // boxen终端打印样式 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) } // 获取用户想要使用的包管理工具 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) }

``` only-allow 期待的包管理器和运行的包管理器对比。匹配失败,则提示并报错。而which-pm-runs 通过获取 process.env.npm_config_user_agent 变量获取到当前运行脚本的包管理器和版本号