【第20期】install-pkg

121 阅读1分钟

今天的源码分析的是 install-pkg, 作者是 Anthony Fu, Vue 核心成员, 也是 Vueuse的作者.

该包的功能是

Install package programmatically. Detect package managers automatically (npm, yarn and pnpm).

以编程方式安装包。自动检测包管理器(npm、yarn 和 pnpm)。

源码分析

主要的源码文件有两个, 下面分别分析下

index.ts
// 命令行脚本执行工具
import execa from 'execa'
import { detectPackageManager } from '.'export interface InstallPackageOptions {
  cwd?: string
  dev?: boolean
  silent?: boolean
  packageManager?: string
  preferOffline?: boolean
  additionalArgs?: string[]
}
​
export async function installPackage(names: string | string[], options: InstallPackageOptions = {}) {
  // 获取当前使用的包管理工具, 默认是 npm
  const agent = options.packageManager || await detectPackageManager(options.cwd) || 'npm'
  // 需要安装的包, 如果只有一个要放到数组里
  if (!Array.isArray(names))
    names = [names]
    
  // 其他参数
  const args = options.additionalArgs || []
​
  if (options.preferOffline)
    args.unshift('--prefer-offline')
​
  // 执行命令, 例如 npm install vue
  return execa(
    agent,
    [
      agent === 'yarn'
        ? 'add'
        : 'install',
      options.dev ? '-D' : '',
      ...args,
      ...names,
    ].filter(Boolean), // 过滤掉空串
    {
      stdio: options.silent ? 'ignore' : 'inherit',
      cwd: options.cwd,
    },
  )
}
​
detect.ts
import path from 'path'
import findUp from 'find-up'export type PackageManager = 'pnpm' | 'yarn' | 'npm'const LOCKS: Record<string, PackageManager> = {
  'pnpm-lock.yaml': 'pnpm',
  'yarn.lock': 'yarn',
  'package-lock.json': 'npm',
}
​
export async function detectPackageManager(cwd = process.cwd()) {
  // 根据数组中的文件名,找到对应的文件路径,并返回, 如果存在多个则返回找到的第一个, 因此 LOCKS 里的顺序也反应了作者对于包管理器的认可程度
  const result = await findUp(Object.keys(LOCKS), { cwd })
  // path.basename() 返回路径中的文件名
  const agent = (result ? LOCKS[path.basename(result)] : null)
  return agent
}
​

如果我们执行了如下函数

installPackage('vite');

那么就能够通过代码来安装 vite

image.png

除了源码中的内容, 这里还使用到了 esno, Node.js runtime enhanced with esbuild for loading TypeScript & ESM, 可以直接运行 .ts 文件

\