- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第20期,链接:juejin.cn/post/708311…。
今天的源码分析的是 install-pkg
, 作者是 Anthony Fu
, Vue 核心成员, 也是 Vueuse
的作者.
该包的功能是
Install package programmatically. Detect package managers automatically (
npm
,yarn
andpnpm
).以编程方式安装包。自动检测包管理器(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
除了源码中的内容, 这里还使用到了 esno
, Node.js runtime enhanced with esbuild for loading TypeScript & ESM
, 可以直接运行 .ts
文件
\