Skip to main content

vuecli源码解析(3)

· One min read
Oxygen

image-20220122161800174

vue-cli-service作为第一个必然会被调用的plugin,其功能主要是生成项目模板文件,以及通过servebuild等命令进行开发环境server的启动和生产环境的构建打包等。下面分析其内部逻辑。

检查 Node 版本

vue-cli-service位于@vue/cli-service目录下,通过package.json找到其入口程序为bin/vue-cli-service.js,首先依旧是检查 Node 版本。

初始化Service实例

传入执行当前命令的目录,也就是创建项目的文件夹,来初始化Service实例。

image-20220122182531357

加载项目运行程序和webpack配置项

image-20220122183108440

resolvePlugins会从上层的commands以及config目录加载进来所有index.js文件。commands目录下包括开发环境执行程序serve.js以及生产环境打包build.js等,config目录包含webpack的配置程序,都是项目运行所需的程序,因为通过@vue/cli创建的项目不会暴露webpack等配置项,所以需要这些程序来执行。

这些程序被看做plugin,包含一个id作为标识符,和一个apply方法,需要执行的时候调用apply方法即可。

image-20220123135153677

然后还会对plugins进行排序。

serve.js

serve.js是开发环境下启动 webpack dev server 的程序,其返回的是一个函数,函数内部通过调用api.registerCommand传递了三个参数,那么serve.js通过plugin的方式注册,肯定会有执行的时候,见下文继续探索。

image-20220122184906777

并且导出的模块还有一个defaultModes对象,包含命令名称和环境变量参数的映射关系,这样Service实例内部可以通过defaultModes获取当前程序执行的环境。

image-20220122184932953

image-20220122190528586

build.js

build.js是生产环境的打包程序,则通过调用api.registerCommand传递build字符串等参数,以及暴露了production的环境变量。

image-20220123153348102

image-20220123153415916

css.js

config目录下的css.js为例,其通过api.chainWebpack来配置webpack

image-20220123200053836

注册命令行参数

初始化完Service实例,加载完项目所需要的所有执行程序,然后会执行run方法,run内部首先会走init方法。

image-20220122185844560

image-20220122190940124

加载env

init方法内部会加载指定环境的.env文件内部设置环境变量参数,这里使用了dotenvdotenv-expand这两个库来加载.env文件的环境变量到process.env中。

image-20220123153707199

image-20220123160135916

获取项目配置项

在加载了环境变量参数以后,会调用loadUserOptions方法,loadUserOptions内部会调用loadFileConfig获取项目内部的vue.config.js等形式的配置文件。

image-20220123160527552

然后用户项目配置项会传入loadedCallback函数内部,使用lodash.defaultsDeepvue-cli-service内部的默认配置合并。

image-20220123161123293

image-20220123160841575

注入PluginAPI实例

loadedCallback内部会调用每个pluginapply方法,传入PluginAPI的实例和当前项目的配置项作为参数。

image-20220123160950689

其中PluginAPI在初始化的时候传递了两个参数:

  • idplugin程序的名称
  • this:指向当前的Service实例

在构造函数内部初始化以后,Service实例会挂载在PluginAPI实例的service属性上。

image-20220123162103664

上文介绍到apply也就是serve.js等构建模块导出的函数,其接收两个参数:

  • apiPluginAPI的实例
  • options:项目的配置项

PluginAPI内部定义了一系列方法可以通过api来调用,其中api.registerCommand是往Service实例的commands上注册vue-cli-service的 CLI 命令参数名称serve,不过这里只是注册,并没有开始执行,所以到这里程序的目的只是将构建项目需要的程序加载进来,并且和命令行参数对应起来而已。

image-20220122184906777

image-20220123162213927

后面的话,如果在配置文件中包含chainWebpackwebpackConfig配置项也会挂载到Service实例的webpackChainFnswebpackRawConfigFns属性上。

组合webpack配置项

上文说到config目录下的程序会通过api.chainWebpack注册一些 webpack 的配置项,这些配置项会保存在Service实例的webpackChainFnswebpackRawConfigFns内部。

image-20220123200323198

执行程序

命令行参数现在和执行程序已经通过init方法关联起来了,接下来便是找到在 CLI 输入的命令参数对应的执行程序,然后执行。

接着看run方法内部的逻辑。这里通过this.commands找到了和命令行参数name对应的执行程序command,然后便调用command.fn这个方法,也就是serve.js内部传递的回调函数,也就是开发环境启动 webpack dev server 等操作。

image-20220123162926937