我们一般在创建vue项目时会通过cli脚手架创建,执行vue create hello-world,如果没有安装vue命令可以先全局安装npm install -g @vue/cli,目前我安装的是5.0.4版本的还是比较新的,那我们怎么通过命令去启动整个项目呢。
vue-cli-service serve
当我们下载完脚手架后会执行npm run serve来启动项目,这时什么原因呢,我们来看下它的脚本命令
我们在执行npm run serve时,npm会帮助我们执行vue-cli-service serve,那为什么可以执行vue-cli-service这句命令呢,我们来看看package.json
我们去node_modules找@vue/cli-service这个包,在该包的package.json内我们可以找到下面这么一个属性bin
npm在查到当前的bin后会将bin/vue-cli-service.js这个文件做一个软链接放置在node_modules/.bin/目录下,如下所示
所以当我们执行npm run serve实际执行的是node_modules/@vue/cli-service/bin/vue-cli-service.js的这个文件。
vue-cli-service.js
现在来看下vue-cli-service.js这个文件是怎么执行的。
可以看到主要是
- 引入
Service new Service一个service对象service.run
Service.js初始化
我们先来看看Service函数做了什么,Service来自./lib/Service.js
当我们new Service时会先执行构造函数,这里赋了一些初始化的值,这里主要是
package.json内的作为对象赋值给了this.pkg- 将数组对象
[{id: '插件路径', apply: '对应插件导出函数'},...]赋值给了this.plugins - 将解析每个命令要使用的默认模式赋值给
this.mode
server.run
new Service之后会执行server.run方法
- 设置
mode为development环境,因为我们执行的是vue-cli-service serve - 执行
this.init(mode) - 执行
fn(args, rawArgv)
server.init
上面我们执行到了this.init,这里主要做了
this.loadEnv(mode),处理环境变量,将process.env.NODE_ENV和process.env.BABEL_ENV设置为developmentthis.loadUserOptions()获取用户在vue.config.js下的配置- 执行
loadedCallback回调
在loadedCallback回调中,主要做了
this.plugins.forEach,调用插件的apply方法,apply就是./commands/serve.js导出的函数,并传入了new PluginAPI(id, this)和this.projectOptions这两参数
PluginAPI来自当前目录下的PluginAPI.js文件
可以看到PluginAPI的constructor传入的id就是build-in:commands/serve,service就是之前new的Service实例对象
-
this.projectOptions是vue-cli默认的配置和vue.config.js合并后的配置 -
在
./commands/serve.js导出的函数中,执行api.registerCommand,就是在执行PluginAPI中的registerCommand方法,name就是serve,所以就是在service.commands上赋值{ fn, opts: opts || {} }
apply执行完后,将配置中的chainWebpack和configureWebpack分别放入webpackChainFns和webpackRawConfigFns队列中
- 最后从
service.commamds中导出fn执行
这个fn就是./commands/serve.js导出函数中的最后一个回调参数serve
async function serve()
这个serve回调函数主要做了
- 执行
api.chainWebpack
而api就是PluginApi,即执行service.webpackChainFns.push(fn)
- 执行
api.resolveWebpackConfig,就是执行service.resolveWebpackConfig方法,可以看到之后执行chainableConfig.toConfig将链式配置转成普通的配置对象,执行this.webpackRawConfigFns.forEach将普通的配置对象进行合并
所以最后就是导出最终可以被webpack解析的配置
- 最终就将配置传入
webpack,启动webpack-dev-server来启动服务
总结
vue-cli的启动其实还算复杂,但是我们通过断点调试看是能够看清整个启动的流程,在其中我们也发现可以在vue.config.js也可以配置chainWebpack这种链式配置也可以配置configureWebpack这种普通配置。