text
Usually, installation dependencies are installed in imperative ways. Have you ever thought that you can install dependencies programmatically?
install-pkg
It is a tool for installing dependencies. It can install dependencies in different environments, such as npm, yarn, pnpm, etc.
Source code address:/antfu/insta…
use
install-pkg
It is very simple to use, according toREADME
The following code can be used to install the dependencies:
import { install } from 'install-pkg' await installPackage('vite', { silent: true })
Source code analysis
install-pkg
The source code of the 100 lines is very simple, so let's take a look at its implementation principle.
according toREADME
We can use the instructionsinstallPackage
How to install dependencies, let's take a look firstinstallPackage
Method implementation:
installPackage
Method insrc/
In the file, the code to convert it to js is as follows:
import execa from 'execa' import { detectPackageManager } from '.' export async function installPackage(names, options = {}) { const detectedAgent = || await detectPackageManager() || 'npm' const [agent] = ('@') if (!(names)) names = [names] const args = || [] if () { // yarn berry uses --cached option instead of --prefer-offline if (detectedAgent === 'yarn@berry') ('--cached') else ('--prefer-offline') } return execa( agent, [ agent === 'yarn' ? 'add' : 'install', ? '-D' : '', ...args, ...names, ].filter(Boolean), { stdio: ? 'ignore' : 'inherit', cwd: , }, ) }
It can be seen that it is an asynchronous method, which receives two parameters, the first parameter is the dependency name to be installed, and the second parameter is the configuration item.
Inside the method, first pass the incoming configuration itemoptions
Come and get itpackageManager
, if not transmittedpackageManager
, thendetectPackageManager
Method to obtainpackageManager
,ifdetectPackageManager
The method was not obtainedpackageManager
, then default to usenpm
。
Come and have a lookdetectPackageManager
Method implementation:
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', '': 'pnpm', '': 'yarn', '': 'npm', '': 'npm', } export async function detectPackageManager(cwd = ()) { let agent = null const lockPath = await findUp((LOCKS), { cwd }) let packageJsonPath if (lockPath) packageJsonPath = (lockPath, '../') else packageJsonPath = await findUp('', { cwd }) if (packageJsonPath && (packageJsonPath)) { try { const pkg = ((packageJsonPath, 'utf8')) if (typeof === 'string') { const [name, version] = ('@') 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 ('[ni] Unknown packageManager:', ) } } catch {} } // detect based on lock if (!agent && lockPath) agent = LOCKS[(lockPath)] return agent }
findUp
is a tool for finding files that can search for files from the current directory until they are found.
Let's analyze it step by step:
const lockPath = await findUp((LOCKS), {cwd}) let packageJsonPath if (lockPath) packageJsonPath = (lockPath, '../') else packageJsonPath = await findUp('', {cwd})
At the beginning it is to obtain、
、
path to the file;
If you find it, it will be easy. Just look for it in this file directoryJust file;
If not found, continue to usefindUp
Method to finddocument.
if (packageJsonPath && (packageJsonPath)) { try { const pkg = ((packageJsonPath, 'utf8')) // ... } catch { } }
If foundThe file is read and then parsed into a JSON object.
if (typeof === 'string') { const [name, version] = ('@') 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 ('[ni] Unknown packageManager:', ) }
Used herepackageManager
To determine which package manager to use;
- if
packageManager
yesyarn
, and the version number is greater than1
, then useyarn@berry
; - if
packageManager
yespnpm
and the version number is less than7
, then usepnpm@6
; - if
packageManager
yesyarn
、pnpm
、npm
、bun
One of them will be used directly; - Otherwise, print a warning.
// detect based on lock if (!agent && lockPath) agent = LOCKS[(lockPath)]
If not passedCome and get it
packageManager
, thenlockPath
Come and get itpackageManager
。
The core of this method is to obtain it through two wayspackageManager
:
- pass
In-house
packageManager
Field; - pass
lock
File to get.
It can be said to be very clever.
Let's continue watchinginstallPackage
method:
const detectedAgent = || await detectPackageManager() || 'npm' const [agent] = ('@')
Here is the first line, which is to obtainpackageManager
, complement the above method, continue reading:
if (!(names)) names = [names]
Here isname
It is unified into an array for easy subsequent processing.
const args = || [] if () { // yarn berry uses --cached option instead of --prefer-offline if (detectedAgent === 'yarn@berry') ('--cached') else ('--prefer-offline') }
Here is the processingpreferOffline
Parameters, if this parameter is set, it will beargs
Added in--prefer-offline
or--cached
Parameters, becauseyarn@berry
andnpm
The parameters are different.
return execa( agent, [ agent === 'yarn' ? 'add' : 'install', ? '-D' : '', ...args, ...names, ].filter(Boolean), { stdio: ? 'ignore' : 'inherit', cwd: , }, )
The command here is based onpackageManager
To splice,yarn
andnpm
The commands are different, so you need to make a judgment.
Finally, execute the installation command, which is used hereexeca
to execute commands, the usage of this library andchild_process
Almost the same, but more convenient, refer to:execa。
Summarize
By learning this library, we can learn a lot, such as:
- How to determine the package manager used by the user;
- How to find files;
- How to use
execa
to execute the command.
At the same time, there are many interspersed herenode
knowledge and knowledge of package manager, such as:
-
node
ofmethod;
- Package Manager
lock
document; - Package manager parameters and commands.
The above is the detailed content of the source code analysis of program installation dependency install-pkg. For more information about program installation dependency install-pkg, please pay attention to my other related articles!