vue2.X之vue-cli源码学习

440 阅读4分钟

前言

熟悉vue开发的同学肯定对vue-cli不陌生,Vue-cli是一款基于模板化的开发工具,等于就是把别人的项目结构给照搬过来,所有的配置都是暴露出来的,你可以根据实际情况去做一些配置的修改,更加灵活自由一点。前段时间也学习了下cli的源码,特此来记录下。

常见 npm 包

在正式开始cli源码之前,先介绍下一些常用的npm包

  • commander:一款重量轻,表现力和强大的命令行框架,提供了用户命令行输入和参数解析强大功能。
  • handlebars:一个 javascript 语义模版库。可以利用 Handlebars.registerHelper 方法注册了一些 helper,这样就可以在模板中方便的使用这些 helper
  • metalsmith:静态网站生成器,可以用在批量处理模板的场景。它最大的特点就是所有的逻辑都是由插件处理,你只需要将这些插件用 metalsmith 连接起来使用即可。
  • chalk:用于修改控制台字符串的样式,包括字体样式(加粗),颜色以及背景颜色等。
  • download-git-repodownload-git-repo 是用于 从 GitHub, GitLab, Bitbucket 下载一个 git 仓库。
  • consolidateconsolidate 是一个模版引擎整合库。

vue-init 流程图

从图中可以看出init主要分为两步:

  1. 拉取模版
  2. 渲染模版

接下去将根据源码对每一步进行说明。

注册命令

从图中可以看出vue-init的使用方法为vue-init template-name project-name。同时他提供了-c和--offline这两个选项。其中-c代表是利用git拉取模版,--offline使用缓存的模板,位于~/.vue-templates目录下面。

输入命令后,会利用commend包来分别读取模版名称,文件名,以及选项,并根据选项来进行后续的模版拉取操作,从代码中可以看到。本地存储模版的路径为根目录下的.vue-templates文件夹。

这段代码的作用是:

  1. 如果没有填写 app-name ,则默认在当前目录生成模版。
  2. 如果当前目录有与 app-name 重名的,是否要继续。 然后根据用户的回答执行run函数来拉取模版及渲染模版到目录中。

拉取模版

我们来看一下run函数

run函数会先判断是否是本地模版,如果是,会判断是否存在,存在则调用generate函数进行渲染,不存在则提醒。 如果不是本地模版,则判断是否是官方模版进行路径及版本的判断,再调用downloadAndGenerate方法。

downloadAndGenerate会先判断本地是否存在模版,如果存在则删除,在调用download方法。

download方法主要根据选项clone来判断是调用git还是http方法去下载模版,下载成功后执行回调generate函数进行模版的渲染。

模版渲染

整体来看generate函数还是比较晦涩难懂的,接下来,我们对这个方法分块来阅读。 首先来看getOption方法

getOption中会先从模版的template文件夹中的meta.json或者meta.js来读取配置,之后对你输入的文件名进行验证,同时添加些默认的配置。其中meta.jsonmeta.js是动态加载模版的关键。

截取webpack模版中的meta.js,其中的message和default是否觉得很熟悉。

接着通过metalsmith获取模版下的template文件夹做为后续的文件模版。再通过Handlebars.registerHelper注册逻辑命令,从而处理一些数据,像webpack中就注册了if_eq来判断是否相等。

注册完命令之后会执行meta.js中的before函数,webpack中的方法为addTestAnswers

metalsmith.before 结果就是将 metalsmith metadata 数据和 isNotTest 合并,如果 isTest 为 ture,还会自动设置 name,description等字段。它的作用就是为模版添加自动测试脚本,它会将 isNotTest 设置为 false,而通过 inquirer 来提问又会是在 isNotTest 为 true 的情况下才会发生,因此设置了VUE_TEMPL_TEST的值会省略 inquirer 提问过程,并且会根据你设置的值来生成对应的模板,有以下三种值可以设置:

  1. minimal:这种不会设置 router,eslint 和 tests
  2. full: 会带有 router,eslint (standard) 和 tests (jest & e2e)
  3. full-airbnb-karma:带有 router eslint(airbnb) 和 tests(karma) 具体的使用方式:
VUE_TEMPL_TEST=full vue init webpack demo

调用完before函数后会调用metalsmith.use来使用askQuestionfilterFilesrenderTemplateFiles这三个插件。下面逐个来看这三个插件是干啥的。 askQuestion调用了ask函数。

ask函数就是通过 inquirer.prompt 来实现命令行交互,并将交互的值通过 metalsmith.metadata() 存到全局,然后在渲染模板的时候直接获取这些值。

filterFiles则是通过用户的回答将一些需要过滤调的文件删除

renderTemplateFiles 的主要功能就是利用 consolidate.handlebars.render~/.vue-templates下面的 handlebars 模板文件渲染成正式的文件。

之后执行afterbuild函数完成整个渲染流程。

结语

至此,vue-init的整个流程及源码就结束了,其实整体流程还是比较清晰的,通过对次源码的学习我们在日后可以构建自己的脚手架和模版。毕竟懒惰是第一生产力!