我们先来看下config命令的配置
packages/@vue/cli/bin/vue.js
program
.command('config [value]')
.description('inspect and modify the config')
.option('-g, --get <path>', 'get value from option')
.option('-s, --set <path> <value>', 'set option value')
.option('-d, --delete <path>', 'delete option from config')
.option('-e, --edit', 'open config with default editor')
.option('--json', 'outputs JSON result only')
.action((value, options) => {
require('../lib/config')(value, options)
})
config命令是用来检查和修改cli的配置的,它有以下选项:
- '-g, --get ':获取指定路径的配置
- '-s, --set ':修改指定路径的配置
- '-d, --delete ':删除指定路径的配置
- '-e, --edit':使用默认编辑器打开配置文件
- '--json':将配置以json格式输出
命令处理函数中在../lib/config文件中,我们打开该文件可以看到导出了configure函数。
packages/@vue/cli/lib/config.js
module.exports = (...args) => {
return configure(...args).catch(err => {
error(err)
if (!process.env.VUE_CLI_TEST) {
process.exit(1)
}
})
}
接下来我们来一一分析该函数
const fs = require('fs-extra')
const path = require('path')
const homedir = require('os').homedir()
const { get, set, unset, error, launch } = require('@vue/cli-shared-utils')
const file = path.resolve(homedir, '.vuerc')
const config = await fs.readJson(file)
方法的一开始找到了cli的配置文件.vuerc,然后读取该文件并进行了保存。接下来是一一处理各选项。
--json选项:
if (!options.delete && !options.get && !options.edit && !options.set) {
if (options.json) {
console.log(JSON.stringify({
resolvedPath: file,
content: config
}))
} else {
console.log('Resolved path: ' + file + '\n', JSON.stringify(config, null, 2))
}
}
如果命令的选项是json的话,则将配置文件的地址及配置内容放置在一个对象里以JSON字符串的格式输出。如果命令选项是除了delete、get、edit、set之外的其它选项时,则直接输出配置文件的地址和配置信息。如下:
-g, --get <path>选项:
if (options.get) {
// eslint-disable-next-line no-shadow
const value = get(config, options.get)
if (options.json) {
console.log(JSON.stringify({
value
}))
} else {
console.log(value)
}
}
get方法
packages/@vue/cli-shared-utils/lib/object.js
exports.get = function (target, path) {
// 将路径以.进行切割,obj1.obj2 -> [obj1,obj2]
const fields = path.split('.')
// 保存传入的全部配置信息
let obj = target
const l = fields.length
// 然后一一递归找到需要查找的配置信息
for (let i = 0; i < l - 1; i++) {
const key = fields[i]
if (!obj[key]) {
return undefined
}
obj = obj[key]
}
// 返回找到的配置信息
return obj[fields[l - 1]]
}
调用get方法,传入配置文件及要查找的配置信息的路径,输出查到到的配置信息,如果命令选项中带有json,则将该配置信息转换为JSON字符串后再输出。如下:
-s, --set <path> <value>选项:
if (options.set && !value) {
throw new Error(`Make sure you define a value for the option ${options.set}`)
}
if (options.set && value) {
console.log(config, options.set, value)
set(config, options.set, value)
if (value.match('[0-9]')) {
set(config, options.set, parseInt(value))
}
if (value === 'true') {
set(config, options.set, true)
}
if (value === 'false') {
set(config, options.set, false)
}
// 重新写入
await fs.writeFile(file, JSON.stringify(config, null, 2), 'utf-8')
if (options.json) {
console.log(JSON.stringify({
updated: options.set
}))
} else {
console.log(`You have updated the option: ${options.set} to ${value}`)
}
}
set方法
packages/@vue/cli-shared-utils/lib/object.js
exports.set = function (target, path, value) {
// 将路径以.进行切割,obj1.obj2 -> [obj1,obj2]
const fields = path.split('.')
// 保存传入的全部配置信息
let obj = target
const l = fields.length
// 然后一一递归找到需要查找的配置信息
for (let i = 0; i < l - 1; i++) {
const key = fields[i]
if (!obj[key]) {
obj[key] = {}
}
obj = obj[key]
}
// 修改找到的配置信息
obj[fields[l - 1]] = value
}
set选项必须要携带配置的新值,不然会报错。由于命令携带的参数均会被转为字符串,所以我们需要单独处理下数字及布尔值。修改完成后,再重新将配置写入.vuerc配置文件,再将更新的信息打印出来。如下:
-d, --delete <path>选项:
if (options.delete) {
unset(config, options.delete)
await fs.writeFile(file, JSON.stringify(config, null, 2), 'utf-8')
if (options.json) {
console.log(JSON.stringify({
deleted: options.delete
}))
} else {
console.log(`You have removed the option: ${options.delete}`)
}
}
unset方法
packages/@vue/cli-shared-utils/lib/object.js
exports.unset = function (target, path) {
// 将路径以.进行切割,obj1.obj2 -> [obj1,obj2]
const fields = path.split('.')
// 保存传入的全部配置信息
let obj = target
const l = fields.length
const objs = []
/*
将数据以如下格式保存到objs里,删掉obj2之后,obj1则是一个空对象,则把obj1也删掉,
{
parent: {
...,
obj1: {
obj2: "value"
}
},
key: 'obj1',
value: { obj2: "value" }
}
*/
for (let i = 0; i < l - 1; i++) {
const key = fields[i]
if (!obj[key]) {
return
}
objs.unshift({ parent: obj, key, value: obj[key] })
obj = obj[key]
}
// 删掉目标对象
delete obj[fields[l - 1]]
// 清除空的对象
for (const { parent, key, value } of objs) {
if (!Object.keys(value).length) {
delete parent[key]
}
}
}
先将选项中携带的目标对象删掉,修改完成后,再重新将配置写入.vuerc配置文件,再将更新的信息打印出来。如下:
-e, --edit选项:
if (options.edit) {
launch(file)
}
launch方法:
packages/@vue/cli-shared-utils/lib/launch.js
const launch = require('launch-editor')
exports.launch = (...args) => {
// 要打开的文件路径
const file = args[0]
console.log(`Opening ${file}...`)
// 文件打开之后的回调函数
let cb = args[args.length - 1]
if (typeof cb !== 'function') {
cb = null
}
// 用编辑器打开文件
launch(...args, (fileName, errorMessage) => {
console.error(`Unable to open '${fileName}'`, errorMessage)
console.log(`Try setting the EDITOR env variable. More info: https://github.com/yyx990803/launch-editor`)
if (cb) cb(fileName, errorMessage)
})
}
以上便是vue config命令的全部解析~