文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

install-pkg怎么安装和使用

2023-07-04 21:00

关注

本文小编为大家详细介绍“install-pkg怎么安装和使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“install-pkg怎么安装和使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

正文

通常安装依赖都是通过命令式的方式来安装,有没有想过可以通过编程式的方式来安装依赖呢?

install-pkg是一个用于安装依赖的工具,它可以在不同的环境下安装依赖,比如 npm、yarn、pnpm 等。

使用

install-pkg的使用非常简单,根据README的说明,就通过下面的代码就可以安装依赖了:

import { install } from 'install-pkg'await installPackage('vite', { silent: true })

源码分析

install-pkg的源码非常简单,只有 100 行左右,我们来看看它的实现原理。

根据README的说明,我们可以通过installPackage方法来安装依赖,那么我们先来看看installPackage方法的实现:

installPackage方法在src/index.ts文件中,转成 js 代码如下:

import execa from 'execa'import { detectPackageManager } from '.'export async function installPackage(names, options = {}) {  const detectedAgent = options.packageManager || await detectPackageManager(options.cwd) || 'npm'  const [agent] = detectedAgent.split('@')  if (!Array.isArray(names))    names = [names]  const args = options.additionalArgs || []  if (options.preferOffline) {    // yarn berry uses --cached option instead of --prefer-offline    if (detectedAgent === 'yarn@berry')      args.unshift('--cached')    else      args.unshift('--prefer-offline')  }  return execa(    agent,    [      agent === 'yarn'        ? 'add'        : 'install',      options.dev ? '-D' : '',      ...args,      ...names,    ].filter(Boolean),    {      stdio: options.silent ? 'ignore' : 'inherit',      cwd: options.cwd,    },  )}

可以看到是一个异步方法,它接收两个参数,第一个参数是要安装的依赖名称,第二个参数是配置项。

在方法内部,首先通过传入的配置项options来获取packageManager,如果没有传入packageManager,则通过detectPackageManager方法来获取packageManager,如果detectPackageManager方法也没有获取到packageManager,则默认使用npm

来看看detectPackageManager方法的实现:

import fs from 'fs'import path from 'path'import findUp from 'find-up'const AGENTS = ['pnpm', 'yarn', 'npm', 'pnpm@6', 'yarn@berry', 'bun']const LOCKS = {  'bun.lockb': 'bun',  'pnpm-lock.yaml': 'pnpm',  'yarn.lock': 'yarn',  'package-lock.json': 'npm',  'npm-shrinkwrap.json': 'npm',}export async function detectPackageManager(cwd = process.cwd()) {  let agent = null  const lockPath = await findUp(Object.keys(LOCKS), { cwd })  let packageJsonPath  if (lockPath)    packageJsonPath = path.resolve(lockPath, '../package.json')  else    packageJsonPath = await findUp('package.json', { cwd })  if (packageJsonPath && fs.existsSync(packageJsonPath)) {    try {      const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))      if (typeof pkg.packageManager === 'string') {        const [name, version] = pkg.packageManager.split('@')        if (name === 'yarn' && parseInt(version) > 1)          agent = 'yarn@berry'        else if (name === 'pnpm' && parseInt(version) < 7)          agent = 'pnpm@6'        else if (name in AGENTS)          agent = name        else          console.warn('[ni] Unknown packageManager:', pkg.packageManager)      }    }    catch {}  }  // detect based on lock  if (!agent && lockPath)    agent = LOCKS[path.basename(lockPath)]  return agent}

findUp是一个用于查找文件的工具,它可以从当前目录向上查找文件,直到找到为止。

我们来逐行分析:

const lockPath = await findUp(Object.keys(LOCKS), {cwd})let packageJsonPathif (lockPath)    packageJsonPath = path.resolve(lockPath, '../package.json')else    packageJsonPath = await findUp('package.json', {cwd})

最开始是获取package-lock.jsonyarn.lockpnpm-lock.yaml等文件的路径;

如果找到就好办了,直接在这个文件目录下找package.json文件即可;

如果没找到就继续使用findUp方法来查找package.json文件。

if (packageJsonPath &amp;&amp; fs.existsSync(packageJsonPath)) {    try {        const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))        // ...    } catch {    }}

如果找到了package.json文件,就读取文件内容,然后解析成 JSON 对象。

if (typeof pkg.packageManager === 'string') {    const [name, version] = pkg.packageManager.split('@')    if (name === 'yarn' && parseInt(version) > 1)        agent = 'yarn@berry'    else if (name === 'pnpm' && parseInt(version) < 7)        agent = 'pnpm@6'    else if (name in AGENTS)        agent = name    else        console.warn('[ni] Unknown packageManager:', pkg.packageManager)}

这里是用过packageManager来判断使用哪个包管理器;

// detect based on lockif (!agent && lockPath)    agent = LOCKS[path.basename(lockPath)]

如果没有通过package.json来获取packageManager,则通过lockPath来获取packageManager

这个方法的核心就是通过两个方式来获取packageManager

可以说是非常巧妙。

我们继续看installPackage方法:

const detectedAgent = options.packageManager || await detectPackageManager(options.cwd) || 'npm'const [agent] = detectedAgent.split('@')

这里是第一行,就是获取packageManager,和上面讲的方法相辅相成,继续往下看:

if (!Array.isArray(names))    names = [names]

这里是将name统一变成数组,方便后面处理。

const args = options.additionalArgs || []if (options.preferOffline) {    // yarn berry uses --cached option instead of --prefer-offline    if (detectedAgent === 'yarn@berry')        args.unshift('--cached')    else        args.unshift('--prefer-offline')}

这里是处理preferOffline参数,如果设置了这个参数,就会在args中添加--prefer-offline或者--cached参数,因为yarn@berrynpm的参数不一样。

return execa(    agent,    [      agent === 'yarn'        ? 'add'        : 'install',      options.dev ? '-D' : '',      ...args,      ...names,    ].filter(Boolean),    {      stdio: options.silent ? 'ignore' : 'inherit',      cwd: options.cwd,    },  )

这里的命令是根据packageManager来拼接的,yarnnpm的命令不一样,所以需要判断一下。

最后就是执行安装命令了,这里使用了execa来执行命令,这个库的用法和child_process差不多,但是更加方便。

读到这里,这篇“install-pkg怎么安装和使用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯