vuecli源码解析(2)

上文说到创建完package.json文件并安装plugins的依赖,然后后续会初始化Generator实例,Generator内部会调用各个plugin,涉及到插件机制的实现,这里单独起一篇介绍。
plugin程序
首先了解一下@vue/cli中plugin的开发方式,plugin由一个 Service 插件index.js文件作为引导,此外还可以包含generator.js ,prompts.js这些文件。
index.js可以修改 webpack 配置,创建新的 vue-cli service 命令或者修改已经存在的命令。
generator主要用于拓展项目依赖,创建新的文件或者编辑已经存在的文件;且必须是一个函数。
prompts.js则在创建一个新的项目或者在已有项目中添加新的插件时处理用户选项,通过inquirer实现。
.
├── README.md
├── generator.js # generator(可选)
├── index.js # service 插件
├── package.json
├── prompts.js # prompt 文件(可选)
└── ui.js # Vue UI 集成(可选)
加载plugin
紧接上文继续分析Creator内部的create方法,在安装完@vue/cli内部的vue-cli-service等插件的依赖后,会通过resolvePlugins方法对preset的plugins执行顺序进行排列,保证vue-cli-service始终第一个执行,并且加载plugin内部的generator.js和prompts.js程序,推入apply方法。

初始化Generator
加载完plugin之后,会初始化Generator实例。

plugins排序
在Generator构造函数内部会对plugins进行排序,这个排序有点讲究的,根据代码里的注释来看使用了 leetcode 210 题的算法,这里以后探索。


加载generator程序
初始化的时候还会加载package.json内部的其他插件,放入实例的allPlugins内部。


调用generate方法
初始化完Generator会调用实例的generate方法,generate内部首先会调用initPlugins

initPlugins内部会为每一个plugin初始化一个GeneratorAPI的实例,然后将实例对象传入apply方法,上文说到apply就是plugin内部的generator程序,所以这里就是执行plugin内部的generator。

GeneratorAPI
GeneratorAPI这个类内部包含编写plugin的generator所需要的所有方法,其在初始化的时候接收plugin的名称id,Generator的实例,插件的参数options。其内部定义了生成模板文件的方法render,拓展package.json的依赖项extendPackage等。
vue-cli-service
以vue-cli-service为例,其内部generator程序如下,使用render方法渲染template内部的模板文件,拓展package.json的依赖项以及注入scripts和browserslist字段。

render
render方法会解析传入的文件夹路径,使用globby匹配获取文件夹下的所有文件。对于ejs模板还会调用renderFile方法将参数填入模板内部。

最后通过_injectFileMiddleware推入Generator实例的fileMiddlewares中。

extendPackage

extendPackage内部会拓展Generator实例的pkg属性,也就对应package.json内部的字段。
生成配置文件
继续看generate方法,之后会调用extractConfigFiles方法,extractConfigFiles会获取在package.json内部的配置项字段,例如babel,eslintConfig,browserslist等,将它们对应的有效配置文件名称推入实例的files属性内部,然后删除package.json内部的这些字段。

之后会调用writeFileTree生成所有文件,writeFileTree内部使用fs-extra来操作文件。这样plugin的generator就执行完了。
