CD's blog CD's blog
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

CD_wOw

内卷的行情,到不了的梦
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础原理及工具方法

  • Babel

  • WebComponent

  • 专项知识汇总

    • 图片类型、优化、处理知识点汇总
    • 如何统一 npm 包管理
      • 前置知识
      • 方法一
      • 方法二
    • JS如何做请求并发限制
    • JS如何做实现动画序列播放
    • dotenv如何实现env环境变量注入
  • JavaScript笔记
  • 专项知识汇总
CD
2022-10-28
目录

如何统一 npm 包管理

在使用 vite3 的时候,会发现其内部的包都会统一采用 yarn 或是 pnpm 进行三方依赖管理,且只允许使用指定的包管理工具进行管理,这是怎么做到的呢?带着疑问,发现了他们使用的包:only-allow (opens new window), 发现其简单的通过比对命令行来实现了包的管控,来看看是怎么做到的吧.

# 前置知识

  • package scripts 命令执行钩子 (opens new window)

  • process 对象里都有什么 (opens new window)

  • process.env 参数:

// 查看使用的管理工具及版本
.npm_config_user_agent:'yarn/1.22.17 npm/? node/v16.13.1 win32 x64';
// 输出:
// npm/6.14.5 node/v14.17.1 win32 x64
// yarn/1.22.10 npm/? node/v14.17.1 win32 x64
.npm_package_name // 当前package.name
.npm_execpath: 'C:\\Users\\xxx\\AppData\\Roaming\\npm\\node_modules\\yarn\\bin\\yarn.js' // 绝对路径地址
.
1
2
3
4
5
6
7
8

# 方法一

// package.json
 "preinstall": "node ./scripts/preinstall.js",

// 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)
}
1
2
3
4
5
6
7
8
9
10
11

通过判断运行的包管理工具的绝对路径词缀是否含有/npm/pnpm/yarn 来进行是否要继续运行的操作

# 方法二

only-allow 源码

#!/usr/bin/env node
const whichPMRuns = require("which-pm-runs");
const boxen = require("boxen");

/**
 * argv返回数组的成员依次是命令行的各个部分,真正的参数实际上是从process.argv[2]开始。
 * node argv.js a b c = [ 'node', '/path/to/argv.js', 'a', 'b', 'c' ]
 */
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);
}

// 判断期望的包管理工具是否为yarn/npm/pnpm中的一种,否则报错并退出进程
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 ins123stall" 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

which-pm-runs 也非常简单,接下来往下看:

// which-pm-runs
module.exports = function () {
  // 通过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),
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
编辑 (opens new window)
#JavaScript
上次更新: 2022/12/11, 20:19:48
图片类型、优化、处理知识点汇总
JS如何做请求并发限制

← 图片类型、优化、处理知识点汇总 JS如何做请求并发限制→

最近更新
01
gsap动画库学习笔记 - 持续~
06-05
02
远程组件加载方案笔记
05-03
03
小程序使用笔记
03-29
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CD | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式