您好,登录后才能下订单哦!
本文小编为大家详细介绍“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 packageJsonPath if (lockPath) packageJsonPath = path.resolve(lockPath, '../package.json') else packageJsonPath = await findUp('package.json', {cwd})
最开始是获取package-lock.json
、yarn.lock
、pnpm-lock.yaml
等文件的路径;
如果找到就好办了,直接在这个文件目录下找package.json
文件即可;
如果没找到就继续使用findUp
方法来查找package.json
文件。
if (packageJsonPath && 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
来判断使用哪个包管理器;
如果packageManager
是yarn
,并且版本号大于1
,则使用yarn@berry
;
如果packageManager
是pnpm
,并且版本号小于7
,则使用pnpm@6
;
如果packageManager
是yarn
、pnpm
、npm
、bun
中的一个,则直接使用;
否则就打印一个警告。
// detect based on lock if (!agent && lockPath) agent = LOCKS[path.basename(lockPath)]
如果没有通过package.json
来获取packageManager
,则通过lockPath
来获取packageManager
。
这个方法的核心就是通过两个方式来获取packageManager
:
通过package.json
中的packageManager
字段;
通过lock
文件来获取。
可以说是非常巧妙。
我们继续看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@berry
和npm
的参数不一样。
return execa( agent, [ agent === 'yarn' ? 'add' : 'install', options.dev ? '-D' : '', ...args, ...names, ].filter(Boolean), { stdio: options.silent ? 'ignore' : 'inherit', cwd: options.cwd, }, )
这里的命令是根据packageManager
来拼接的,yarn
和npm
的命令不一样,所以需要判断一下。
最后就是执行安装命令了,这里使用了execa
来执行命令,这个库的用法和child_process
差不多,但是更加方便。
读到这里,这篇“install-pkg怎么安装和使用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。