npm7.0源码分析(三)之npm config
2024-01-08 21:15:06
前面已经分析了npm如何启动,启动的核心就是拿到命令行参数,然后把这些参数处理成一个个option对象,再根据option对象来决定执行什么样的命令。
Option对象中有一部分是命令相关,比如install、uninstall、publish等等,还有一部分是命令相关的参数,比如-g表示全局安装,-S表示保存到项目依赖中,还有一些是命令行中没有的全局参数。npm命令行中没有的参数,但又想传递给执行的命令,可以采用如下方式:
npm config set [command-name] option-name value
npm config set install prefix /usr/local
把上述命令和如下命令进行对比一下:
npm install --prefix /usr/local
很明显,npm config set
命令的功能和--prefix
选项是相同的,npm config set
命令的意义在于:可以在命令行中定义某个命令的参数,而这个参数可以在代码中进行读取。
当然,npm提供的不仅仅是set
命令,还有get
、delete
、list
等命令,下面我们来看看这些命令是如何实现的,通过这些命令的实现我们可以更深入地了解npm的执行机制。
config命令的入口
在lib/config/index.js
文件中,定义了如下函数:
/**
* npm command: config
*
* @param {object} argv
* @param {string} subcommand
*/
exports.config = function (argv, subcommand) {
var subCmds = ['set', 'get', 'delete', 'edit', 'list']
if (subCmds.indexOf(subcommand) === -1) {
// config without subcommand
return _usage()
} else {
return configCmd[subcommand](argv)
}
}
函数exports.config
是config命令的入口,当执行npm config
命令时,这个函数会被调用。函数首先检查命令行中是否有子命令,子命令包括set
、get
、delete
、edit
和list
。如果没有子命令,则调用_usage()
函数输出帮助信息。如果有子命令,则调用对应的子命令函数。
config命令的子命令
在lib/config/config.js
文件中,定义了如下函数:
const config = exports = module.exports = {}
/**
* npm config set
*
* @param {object} argv
*/
config.set = function (argv) {
var sections = argv.sections
var npm = loadRoot()
var name = argv.name
var value = argv.value
argv.set = true
config.processArgs(sections, npm, argv)
config.save(argv.name, argv.value, npm)
}
/**
* npm config get
*
* @param {object} argv
*/
config.get = function (argv) {
var sections = argv.sections
var npm = loadRoot()
var name = argv.name
config.processArgs(sections, npm, argv)
var value = config.read(argv.name, npm)
console.log(value)
}
/**
* npm config delete
*
* @param {object} argv
*/
config.delete = function (argv) {
var sections = argv.sections
var npm = loadRoot()
var name = argv.name
config.processArgs(sections, npm, argv)
config.remove(argv.name, npm)
}
/**
* npm config edit
*
* @param {object} argv
*/
config.edit = function (argv) {
var npm = loadRoot()
var configPath = config.get(argv).config
spawn(process.env.EDITOR, [configPath]).on('close', function (code) {
if (code) {
return npm.log.error('editor exited with error code', code)
}
npm.commands.rebuild(npm, [], function (er) {
if (er) return npm.log.error('Error: rebuild failed', er)
config.get(argv)
})
})
}
/**
* npm config list
*
* @param {object} argv
*/
config.list = function (argv) {
var npm = loadRoot()
var sections = argv.sections
var name = argv.name
var scope = argv.scope
config.processArgs(sections, npm, argv)
return config.listConfig(argv, npm)
}
这些函数是config命令的子命令函数,每个函数对应一个子命令。
config.set
函数是set
子命令的函数,用于设置npm的配置参数。config.get
函数是get
子命令的函数,用于获取npm的配置参数。config.delete
函数是delete
子命令的函数,用于删除npm的配置参数。config.edit
函数是edit
子命令的函数,用于编辑npm的配置文件。config.list
函数是list
子命令的函数,用于列出npm的配置参数。
config命令的公共函数
在lib/config/config.js
文件中,还定义了一些公共函数,这些函数被config命令的子命令函数使用。
config.processArgs
函数用于处理命令行参数。config.save
函数用于保存npm的配置参数。config.read
函数用于读取npm的配置参数。config.remove
函数用于删除npm的配置参数。config.listConfig
函数用于列出npm的配置参数。
config命令的实现原理
config命令的实现原理很简单,它首先调用config.processArgs
函数处理命令行参数,然后根据不同的子命令调用不同的函数。
set
子命令调用config.save
函数保存npm的配置参数。get
子命令调用config.read
函数读取npm的配置参数。delete
子命令调用config.remove
函数删除npm的配置参数。edit
子命令调用spawn
函数打开npm的配置文件。list
子命令调用config.listConfig
函数列出npm的配置参数。
如何在代码中使用npm config API
npm config命令提供了丰富的API,我们可以