解读 Vue CLI 4.0 beta 工具链

这篇文章主要会对 vue-cli 工具源码进行一些解读及学习,版本为 4.0.0-beta1

项目结构

lerna

由于整个 vue-cli 中包含了多个项目,比如 cli 对应的 babel, eslint, pwa, ts 等插件,兼容 2.x 版本初始化项目的 cli-init, 启动本地服务的 cli-service 等等,管理多个包项目及发布这里就使用了 lerna

Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.

lerna 作为一个多项目工作流管理工具,支持一些项目的初始化配置工作,并且支持项目中每个包的整体或者独立发布。关于更多 lerna 的介绍和使用,可以参考官方文档以及知乎阿里云中台专栏的使用lerna优雅地管理多个package

packages

packages

如上图所示,大部分的工具都集中在 /packages/@vue 下,大概可以分为以下几类:

commands

cli 以及 cli-init 中承担了大部分 command 的实现,如何初始化项目,添加插件,启动服务,打包,启动 ui 界面等等,其中一部分是在 cli/lib 中有实现,也有一部分单独抽象成了其他的工具在 @vue 下的其他包里。

plugins

上面有提到,有很多辅助的 plugin 。

service

主要是 cli-service 以及 cli-service-global 。负责启动本地服务展示页面,基于 webpack-dev-server 实现,里面也有很多 webpack 的打包配置工作,这里再单独说下,vue-cli 2.x 版本时,初始化项目会把 webpack 配置信息暴露到项目中的 build 以及 config 目录中,而到 3.x 后会隐藏 webpack 配置,如果想单独配置一些打包信息可以新建一个 config 文件,这点与 create-react-app 很像,不过不支持 create-react-app 的 eject 操作来将 webpack 配置弹出到上层。

ui

ui 模块也是 vue-cli 3.x 主推的新功能,通过可视化界面来管理,维护,检测项目状态。

它会有一个全局的项目管理器支持浏览项目,创建及导入:

global-proj

进入到项目中则可以看到 dashboard,插件,依赖,配置和任务管理。

utils

cli-shared-utilscli-test-utils 主要是共用的一些工具方法。

Scripts

项目中有很多工具脚本,存放在 scripts 目录下,

bootstrap

负责给新创建的包做些初始化工作,比如添加 package.json, README.md 和 .npmignore 文件。

buildEditorConfig

创建一个 .editorconfig 文件,里面配置了一些规则比如换行方式,缩进,行最大长度等等。

checkLinks

检查远程链接的网络访问。

genChangeLog, genDocs

生成 change log 以及文档。

patchChromedriver

Appveyor 只支持 Chrome 72 以上,所以这里在 package.json 配置下 chromedriver 版本号。

release, syncDeps

选择发布类型,版本号,同步文件(通过 syncDeps)然后执行 lerna publish 流程。

test, testSetup

测试环境配置及使用 jest 测试

verifyCommitMsg

检查提交 msg, 对文案进行正则检查(版本号及文案开头的提交标识), 不过检查失败的文案貌似不太正确,比如提示说运行 npm run commit 来生成一个提交消息,不过并没有这个脚本。

Commands

命令行接口都在 @vue/cli/bin/vue.js 下,关系如下图所示:

commands

create

@vue/cli/lib/create.js 会进行一层参数检查,错误处理,实际工作会交给同目录下的 Creator.js 去处理,最后一个参数则是需要提示交互的模块,内置的模块列表包括 babel, typescript, pwa, router, vuex, cssPreprocessors, linter, unit, e2e 。

Creator 继承自 EventEmitter, 方便在创建过程中发射一些事件, create 函数则会根据参数来执行创建流程:

1> 是否读取 preset 配置 (远程或存储在本地)
2> 注入服务
3> 一些 legacy support 比如 router, vuex
4> 创建 package manager,优先 yarn
5> 检查 cli 版本
6> 生成 package 对象并将它写入 package.json 文件中
7> 根据配置来决定是否初始化 git
8> 执行 install 安装依赖 (后面也会在有些步骤后执行 install,不再重复)
9> 实例化 Generator 对象并生成相关文件
10> 执行完成后的回调
11> 生成并写入 README 文件
12> 执行 git commit 完成变更提交
13> 写 log, 整个流程结束

add & invoke plugin

add 会检查 git 是否有未提交的 change, 然后也借助 package manager 添加和安装插件,最后 invoke 这个插件。

invoke 的步骤则相对多一点:

1> 检查 git 是否有未提交的 change (同 add)
2> 定位这个插件是否在 pakcage.json 中
3> 加载这个插件的生成器
4> 解析 options, 如果包含 prompt 则提示
5> 生成 plugin 对象然后运行生成器

plugin

这里的生成器也是 create 中的 Generator。

inspect

inspect 命令用来检查 webpack 的配置,借助 vue-cli-service 完成。

对应命令的实现在 cli-service/lib/commands/inspect.js 中,具体步骤不是很复杂,把所有的 webpack rules, loaders, plugins dump 出来。

npx vue-cli-service inspect --mode production 执行后,我们就能拿到 production 环境的 webpack 配置,cli 3.x 使用的是 webpack 4 (5 貌似快发布了),legacy 的 init 则使用的 webpack 3,对比一下两个 cli 版本的配置大部分比较相同,部分的写法不太相同比如 code split 之前使用的是 CommonChunkPlugin, 现在则是 optimization 里单独配置如下:

split

rules 则是增加了一些文件的支持比如 .pug, .stylus, .less 等(之前 .vue 文件里也支持 less 以及 stylus,但是不支持单独的文件 loader,需要手工配置)。plugins 里增加了 VueLoaderPlugin, OptimizeCssnanoPlugin, PreloadPlugin 等等。

serve

serve 命令对应在 cli-service/lib/commands/inspect.js 中,server 部分是基于 webpack-dev-server, 启动的步骤大概如下:

1> 对 webpack 进行配置,比如 source-map, hmr, progress plugin
2> 解析和校验 webpack 配置
3> 暴露状态,入口设置
4> 解析 server 的选项,比如是否使用 https, host 和 port 配置,代理信息等
5> 如果不是生产环境,使用 hot-reload 中间件
6> 构造 server 对象,使用的参数大部分都是之前步骤获取到的,实例化代码如下图所示:

create webpack server

7> return 一个 promise,等待 webpack 编译完成
8> 完成后会把 url 写到剪贴板中,并判断是不是第一次编译,如果是则打开浏览器并加载该 url, 如果有 dashboard,还会通过 ipc manager 发送过去
9> 启动 server,监听指定端口

build

build 的实现在 cli-service/lib/commands/build 目录中,会先确保兼容性区分是不是 legacy build 。然后才开始构建流程:

1> 解析目标地址
2> 解析 webpack 的配置并验证
3> 如果参数中有 dashboard, 借助 DashboardPlugin 把状态暴露出去
4> 如果参数中有 report, 会借助 BundleAnalyzerPlugin 来生成包依赖的报告
5> 执行 webpack 编译
6> 完成后检查是否有错误,并输出一些信息到控制台

ui

ui 部分代码则会多一些,分为前后端两部分。使用的技术栈如下

Front-end:

-- js framework: vue
-- router: vue-router
-- i18n: vue-i18n
-- api: graphql

Server (起名为 appollo):

-- node framework: express
-- static serve: express.static
-- api: graphql
-- database: lowdb
-- cache: lru-cache
-- ...

vue 跟 express 已经很常见了,lowdb 之前没有接触过,是一个基于 node 的纯 json 文件轻量级本地数据库,直接使用一个 json 文件来存储一些需要本地持久化的信息。

其他

还有一些其他的命令比如 init, config, upgrade, info.

-- init 直接调用的 2.9.2 版本的 vue-cli 的 init 命令。
-- config 系统根目录下会有 .vuerc 文件,有一些简单的配置,这里支持 set, get 以及 delete.
-- upgrade 支持整体 upgrade 或者单个 package, 会有一些 migrate 的逻辑。
-- info 通过 envinfo 包来输出一些系统信息到控制台。

到这里几乎对 4.0 beta Vue-Cli 所有的命令及相关工具都进行了简单的解读,欢迎提出建议和指正。

Comments
Write a Comment