前言
2019年10月5日凌晨,Vue 的作者尤雨溪公布了 Vue3 的源代码。当然,它暂时还不是完整的 Vue3,而是 pre-alpha 版,只完成了一些核心功能。github 命名为 vue-next
,寓意下一代 vue 。在笔者发文前,已经有很多大佬陆续发布了一些解读 Vue3 源码的文章。但是,本文并不打算再增加一篇解读源码的文章,而是以项目参与者的视角,通过动手实践,一步步理解和搭建自己的 Vue3 项目。因此,为了达到最佳效果,建议读者,一边阅读本文,一边打开终端跟着一步步动手实践。你将掌握所有构建 Vue3 所必须的知识。
在此之前,建议先将 nodejs 版本升级到 v10.0 以上,笔者测试过,低于 v10.0 以下版本会出现各种揪心的错误,笔者自己使用的是 v10.13.0。
一. 创建项目
1. 创建 github 仓库
2. 克隆仓库到本地
git clone https://github.com/gtvue/vue3.git
cd vue3
git log --oneline && tree -aI .git
可以看到 github 已经帮我们创建了以下三个基础文件,并做了初始化提交。
f9fa484 (HEAD -> master, origin/master, origin/HEAD) Initial commit
.
├── .gitignore
├── LICENSE
└── README.md
二. 参考 vue-next
1. 克隆 vue-next
cd ..
git clone https://github.com/vuejs/vue-next.git
2. 查看 vue-next 目录结构
cd vue-next
tree --dirsfirst -aI ".git*|.vscode|*.lock" -C -L 1
只展开第一级目录,除去 .git 开头,.vscode,以及 .lock 文件,可以看到主要有 3 个目录和 8 个文件。
.
├── .circleci
├── packages
├── scripts
├── .prettierrc
├── README.md
├── api-extractor.json
├── jest.config.js
├── lerna.json
├── package.json
├── rollup.config.js
└── tsconfig.json
3 directories, 8 files
3. 3 个目录
# | directories | what is it ? | how to use ? |
---|---|---|---|
1 | .circleci | 云端持续集成工具 CircleCI 配置目录 |
circleci.com |
2 | packages | 源码目录 | —— |
3 | scripts | 构建脚本目录 | —— |
4. 8 个文件
# | files | what is it ? | how to use ? |
---|---|---|---|
1 | .prettierrc | 代码格式化工具 prettier 的配置文件 |
prettier.io |
2 | README.md | 项目介绍 | —— |
3 | api-extractor.json | TypeScript 的API提取和分析工具 api-extractor 的配置文件 |
api-extractor.com |
4 | jest.config.js | JavaScript 测试框架 jest 的配置文件 |
jestjs.io |
5 | lerna.json | JavaScript 多 package 项目管理工具 lerna 的配置文件 |
lerna.js.org |
6 | package.json | npm 配置文件 | docs.npmjs.com |
7 | rollup.config.js | JavaScript 模块打包器 rollup 的配置文件 |
rollupjs.org rollupjs.com |
8 | tsconfig.json | TypeScript 配置文件 |
tslang.cn typescriptlang.org |
5. 回到初次提交
git checkout `git log --pretty=format:"%h" | tail -1`
git log --pretty=format:"'%an' commited at %cd : %s"
显示,尤雨溪于 2018 年 9 月 19 日 中午 11 点 35 分首次提交了 vue-next
。时至今日已经过去了一年多。
'Evan You' commited at Wed Sep 19 11:35:38 2018 -0400 : init (graduate from prototype)
不妨看看尤大在第一次创建项目时,都添加了那些文件。
$ tree --dirsfirst -aI ".git*|.vscode|*.lock" -C -L 1
.
├── packages
├── scripts
├── .prettierrc
├── lerna.json
├── package.json
├── rollup.config.js
└── tsconfig.json
2 directories, 5 files
对比现在的目录结构,第一次提交的文件要干净一些,具体来说,少了持续集成工具 CircleCI
,测试工具 jest
和 API 提取工具 api-extractor
。只有源码及源码构建和包管理相关的文件。而这些正是整个项目最重要的部分,这里我们可以把它看作是要自己开发一个类似 vue3
的 JavaScript 库所需要的启动工程。可见这些文件对我们来说是非常的重要。为了不“改变历史”,我们不妨 checkout 出一个新的分支,以便尽情查阅。
git checkout -b InitialCommit
6. package.json
了解 JS 项目最重要的文件莫过于 package.json
,它的作用相当于整个项目的总设计图。那么看下尤大在第一次提交时,package.json 到底有啥。
是不是感觉特别清爽,它简洁到只有4个字段。其中我们需要关心的是 scripts
和 devDependencies
。构建脚本非常简单,除了熟悉的 dev
和 build
,还有一个用于对项目源码所有 TypeScript 代码进行格式化的 lint
。开发依赖也是非常精简,是采用 TypeScript 开发,并用 Rollupjs 打包 Js ,最基本的依赖安装。构建脚本 dev
和 build
依然是尤大一直热衷的方式,即将所有构建逻辑放在两个 js 文件中,scripts/dev.js
和 scripts/build.js
,并用 node
解释执行。因此,要了解整个项目的核心构建过程,就需要去研究这两个文件的实现。
6.1 scripts/dev.js
启动开发模式的代码非常简单,只有10几行代码,实际就是使用 execa
执行项目里安装(node_modules)的可执行文件。函数原型为 execa(exefile, [arguments], [options])
,返回一个 Promise
对象。
const execa = require('execa')
const {
targets, fuzzyMatchTarget } = require('./utils')
const target = fuzzyMatchTarget(process.argv[2] || 'runtime-dom')
execa(
'rollup',
[
'-wc',
'--environment',
`TARGET: