1. 源码简介
官网简介:Install package programmatically. Detect package managers automatically (npm, yarn and pnpm)
简单理解,就是用于检查包管理器,自动安装依赖。
2. 使用
npm i @antfu/install-pkgimport { installPackage } from '@antfu/install-pkg'await installPackage('vite', { silent: true })
3. 读源码
从入口 src/index.ts进去看,只对外暴露了两个文件,detect.ts 和 install.ts,意为探测和安装,功能职责划分得很明显。
先看看detect.ts,非常简短的代码,其中 find-up 这个包是用来查找文件路径。
这段代码意思很简单,根据当前目录lock文件,返回它是哪个类型的包管理器(npm | pnpm | yarn)。
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',}/*** @params cwd: current working directory*/export async function detectPackageManager(cwd = process.cwd()) {// /Users/install-pkg/pnpm-lock.yamlconst result = await findUp(Object.keys(LOCKS), { cwd })// pnpmconst agent = (result ? LOCKS[path.basename(result)] : null)return agent}
再看看install.ts,最终结果是用到了 execa 这个包用来执行脚本。
import execa from 'execa'import { detectPackageManager } from '.'export interface InstallPackageOptions {// 目录路径cwd?: string// 安装包是开发还是生产dev?: boolean// stdiosilent?: boolean// 指定包管理packageManager?: string// 离线安装模式, --prefer-offline 优先使用缓存数据preferOffline?: boolean// 额外参数additionalArgs?: string[]}export async function installPackage(names: string | string[], options: InstallPackageOptions = {}) {const agent = options.packageManager || await detectPackageManager(options.cwd) || 'npm'if (!Array.isArray(names))names = [names]const args = options.additionalArgs || []// npm 提供了离线安装模式,使用 --offline, --prefer-offline, --prefer-online 可以指定离线模式。if (options.preferOffline)args.unshift('--prefer-offline')// 最终执行命令类似于 pnpm install -D --prefer-offine release-it react antdreturn execa(agent,[agent === 'yarn'? 'add': 'install',options.dev ? '-D' : '',...args,...names,].filter(Boolean),{// https://nodejs.org/api/child_process.html#optionsstdiostdio: options.silent ? 'ignore' : 'inherit',cwd: options.cwd,},)}

