Vue CLI服务---@vue/cli-service & Vuex
@vue/cli-service
初识
第一块是上一个讲述的cli是把我们代码的配置项,各种各样的插件,npm包给你装好
第二块是这里的cli-service包是提供webpack配置
在cli的Creator中已经内置好了@vue/cli-service,就已经包含了cli-service这部分的webpack的配置
还是先看cli-service的package.json找到bin的入口文件
bin/vue-cli-service.js
代码执行
pnpm i
node vue-cli-service.js
解读
javascript
//首先引入service
const Service = require('../lib/Service')
//基于Service构造函数创建实例
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
const rawArgv = process.argv.slice(2)
//类似于代码压缩的效果,将无用的空格去掉,比如,vue-cli-service build --a --b --c
const args = require('minimist')(rawArgv, {
boolean: [
// build
// FIXME: --no-module, --no-unsafe-inline, no-clean, etc.
'modern',
'report',
'report-json',
'inline-vue',
'watch',
// serve
'open',
'copy',
'https',
// inspect
'verbose'
]
})
const command = args._[0]
service.run(command, args, rawArgv).catch(err => {
error(err)
process.exit(1)
})
平常npm run serve,npm run dev就是执行的是 vue-cli-service serve 和 vue-cli-service dev,最终真正执行的是 node bin/vue-cli-service.js run serve,本质上也就是Commander
run执行的代码,本质上就是针对webpack定制化,或者说webpack配置化的一个能力
javascript
async run (name, args = {}, rawArgv = []) {
// resolve mode
// prioritize inline --mode
// fallback to resolved default modes from plugins or development if --watch is defined
const mode = args.mode || (name === 'build' && args.watch ? 'development' : this.modes[name])
// --skip-plugins arg may have plugins that should be skipped during init()
this.setPluginsToSkip(args, rawArgv)
// load env variables, load user config, apply plugins
await this.init(mode)
args._ = args._ || []
let command = this.commands[name]
if (!command && name) {
error(`command "${name}" does not exist.`)
process.exit(1)
}
if (!command || args.help || args.h) {
command = this.commands.help
} else {
args._.shift() // remove command itself
rawArgv.shift()
}
const { fn } = command
return fn(args, rawArgv)
}
而cli-service包就是创建webpack的过程,generator中的内容就是怎么去封装webpack.config.js的过程
下面的这个就是通过vue-cli创建的默认的模板,里面有标识符,就是ejs模板化语言,在开发中称之为生成模板的过程,使用的就是ejs(嵌入式的js)
Vuex
以Vuex为例,只要提供generator能力,我们就能使用插件化的能力给解析好
generator/index.js
- vue-cli
- packages
- @vue
- cli-plugin-vuex
- generator
- index.js
- generator
- cli-plugin-vuex
- @vue
- packages
store/index.js
- vue-cli
- packages
- @vue
- cli-plugin-vuex
- generator
- template-vue3
- src
- store
- index.js
- store
- src
- template-vue3
- generator
- cli-plugin-vuex
- @vue
- packages
这里对应的就是Vue中Vuex的用法
javascript
import { createStore } from 'vuex'
export default createStore({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
- vue-cli
- packages
- @vue
- cli-plugin-vuex
- index.js
- cli-plugin-vuex
- @vue
- packages
这里是一个入口的返回
javascript
module.exports = (api, options = {}) => {}
目的就是能够使用插件化的能力将其引入进去
vue add vuex
使用这样的命令实现插件化的能力
插件化的能力怎么引入呢?
vue add vuex
- vue-cli
- packages
- @vue
- cli
- bin
- vue.js
- bin
- cli
- @vue
- packages
add是通过引入lib下的add文件来添加插件的
javascript
program
.command('add <plugin> [pluginOptions]')
.description('install a plugin and invoke its generator in an already created project')
.option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
.allowUnknownOption()
.action((plugin) => {
require('../lib/add')(plugin, minimist(process.argv.slice(3)))
})
add这里就是安装一个npm包的过程
- vue-cli
- packages
- @vue
- cli
- lib
- add.js
- lib
- cli
- @vue
- packages
- 判断service的package.json
javascript
const servicePkg = loadModule('@vue/cli-service/package.json', context)
if (servicePkg && semver.satisfies(servicePkg.version, '3.x')) {
// special internal "plugins"
if (/^(@vue\/)?router$/.test(pluginToAdd)) {
return addRouter(context)
}
if (/^(@vue\/)?vuex$/.test(pluginToAdd)) {
return addVuex(context)
}
}
- 安装上面说到的service的包
javascript
log()
log(`📦 Installing ${chalk.cyan(packageName)}...`)
log()
const pm = new PackageManager({ context })
if (pluginVersion) {
await pm.add(`${packageName}@${pluginVersion}`)
} else if (isOfficialPlugin(packageName)) {
const { latestMinor } = await getVersions()
await pm.add(`${packageName}@~${latestMinor}`)
} else {
await pm.add(packageName, { tilde: true })
}
- 然后找目录下的generator,生成generator目录下的文件
javascript
log(`${chalk.green('✔')} Successfully installed plugin: ${chalk.cyan(packageName)}`)
log()
const generatorPath = resolveModule(`${packageName}/generator`, context)
if (generatorPath) {
invoke(pluginName, options, context)
} else {
log(`Plugin ${packageName} does not have a generator to invoke`)
}