vue-cli命令npm run serve 源码解析(二)
前言
上次说到npm run serve 实际上是运行了node vue-cli-service.js
而主要的逻辑是在./lib/Service.js中
今天就来看看./lib/Service.js的源码
构造函数
这个文件export了Service类,其构造函数:
constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {})
主要是 获取 当前命令行的 进程上下文 和一些 配置文件的实例(插件,依赖,配置)
在构造函数中主要做一件事,就是 加载插件
inline是可以理解成为内置的意思
useBuiltIn是一个boolean值,用来判断是否使用内置插件和内置配置
首先会把项目package.json转换成为键值对存储对象:
...
this.pkg = this.resolvePkg(pkg)
...
然后再通过函数resolvePlugins加载所有需需要的插件:
this.plugins = this.resolvePlugins(plugins, useBuiltIn)
this.resolvePlugins(plugins, useBuiltIn)
由@vue\cli-service\bin\vue-cli-service.js代码:
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
可见,inlinePlugins是空的,useBuiltIn是false
而函数最终会返回一个集合plugins
最终返回的plugins有可能会由这三类plugin组成:
- builtInPlugins(这是一定会有的)
- inlinePlugins 和 projectPlugins(项目package.json文件的dependencies)
- localPlugins(vue相关的插件)
1.builtInPlugins
const builtInPlugins = [
'./commands/serve',
'./commands/build',
'./commands/inspect',
'./commands/help',
// config plugins are order sensitive
'./config/base',
'./config/css',
'./config/prod',
'./config/app'
].map(idToPlugin)
可以看到这里内置的插件有哪些,其中./commands/serve就是我们serve指令运行的插件。
2.inlinePlugins 与 projectPlugins
以下代码做了两件事:
1,当inlinePlugins有值的时候,就加载projectPlugins了
这里我个人猜测其实inlinePlugins的来源和projectPlugins其实是一样的,都是项目的package.json,只是如果在其他脚本已经加载过projectPlugins后再使用Service类的话,就不需要重复加载,而我们的npm run serve代码可见以下代码是首次加载,所以就会运行
else代码
2.从this.pkg.dependencies加载projectPlugins 列表。
其中也分两类,一类是必要的插件,一类是可选插件
if (inlinePlugins) {
plugins = useBuiltIn !== false
? builtInPlugins.concat(inlinePlugins)
: inlinePlugins
} else {
const projectPlugins = Object.keys(this.pkg.devDependencies || {})
.concat(Object.keys(this.pkg.dependencies || {}))
.filter(isPlugin)
.map(id => {
if (
this.pkg.optionalDependencies &&
id in this.pkg.optionalDependencies
) {//判断插件是否可选插件
let apply = () => {}
try {
apply = require(id)
} catch (e) {
warn(`Optional dependency ${id} is not installed.`)
}
return { id, apply }
} else {
return idToPlugin(id)
}
})
plugins = builtInPlugins.concat(projectPlugins)//把结果合并到builtInPlugins中
}
3.localPlugins
localPlugins就是从this.pkg.vuePlugins.service加载的插件
if (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {
const files = this.pkg.vuePlugins.service
if (!Array.isArray(files)) {
throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)
}
plugins = plugins.concat(files.map(file => ({
id: `local:${file}`,
apply: loadModule(`./${file}`, this.pkgContext)
})))
}
大部分的item都是由idToPlugin构建的:
{
const idToPlugin = id => ({
id: id.replace(/^.\//, 'built-in:'),
apply: require(id)
})
}
id其实就是js文件的相对地址,只是开头区分了built-in(内置) 或者 local(本地)
最后返回了的plugins会在init的时候用到。
接下来就开始看看Service的run函数

浙公网安备 33010602011771号