引言
Vue
作为当前前端开发中比较重要的框架,在企业级开发中应用十分广泛。目前也是我的主要技术栈之一。在接下来的系列文章中,我将带大家一起探秘Vue.js
底层源码。
本篇文章是Vue源码探秘
的第一篇。在这一篇中,我主要是带大家做一些准备工作,介绍一下flow
、源码目录
和源码构建流程
。
认识flow
flow
是facebook
出品的 JavaScript
静态类型检查工具。Vue.js
的源码利用了 flow
来做静态类型检查,所以了解 flow
有助于我们阅读源码。
为什么用flow
JavaScript
是动态类型语言,它的灵活性有目共睹,但是过于灵活的副作用就是很容易就写出非常隐蔽的隐患代码,在编译期甚至运行时看上去都不会报错,但是可能会发生各种各样奇怪的和难以解决的 bug。
项目越复杂就越需要通过工具的手段来保证项目的维护性和增强代码的可读性。Vue.js
在做 2.0 重构的时候,在 ES2015
的基础上,除了 ESLint
保证代码风格之外,也引入了 flow
做静态类型检查。
flow
在 Vue.js
源码中的应用
flow
常用的两种类型检查方式是:
类型推断
:通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型。类型注释
:事先注释好我们期待的类型,flow 会基于这些注释来判断。
在 Vue.js
的主目录下有 .flowconfig
文件, 它是 flow
的配置文件。
其中的[libs]
用来描述包含指定库定义的目录,这里指向的是项目根目录下的flow
文件夹。打开此目录,可以发现文件结构如下:
里面每个文件分别对应如下:
compiler.js
: 编译相关component.js
: 组件数据结构global-api.js
: 全局 api 相关modules.js
: 第三方库定义options.js
: 选项相关ssr.js
: 服务端渲染相关vnode.js
: 虚拟 node 相关weex.js
: weex 相关
可以看到Vue.js
对于每个模块分别对应的类型定义非常清晰,在阅读源码的过程中,遇到一些想具体了解的类型定义时,可以来到flow
文件夹下,查看具体的类型数据结构的定义。
vue.js
源码目录设计
Vue.js
的源码都在src
目录下:
每个文件夹分别对应如下:
compiler
(编译相关)
├── compiler # 模板解析相关
├── codegen # 代码生成,把 AST(抽象语法树)转换为 render 函数
├── directives # 转换为 render 函数前要执行的指令
├── parser # 把模板解析为 AST
compiler
目录包含 Vue.js
所有编译相关的代码。将 template
模板编译为 render
函数。
在 Vue
中使用 render
函数来创建 VNode
,而在开发的时候我们更多的是使用 template
来编写 HTML
,所以需要将 template
编译为 render
函数。
编译工作可以在构建项目的时候借助 webpack
、vue-loader
等插件来完成,也可以在项目运行时使用 Vue
的构建功能来完成。相对应的构建输出有 runtime
和 runtime-with-compiler
两个版本。由于编译是一项消耗性能的工作,因此推荐使用第一种方式。
core
(核心代码)
├── core # Vue 核心代码
├── components # 全局通用组件 Keep-Alive
├── global-api # 全局 api,即 Vue 对象上的方法,如 extend,mixin,use 等
├── instance # Vue 实例化相关代码,如初始化,事件,渲染,生命周期等
├── observer # 响应式数据修改代码
├── util # 工具函数
├── vdom # 虚拟 DOM 相关代码
core
目录存放了 Vue
的核心代码,里面包括 内置组件、全局 api,Vue 实例化、观察者(响应式数据)、虚拟 DOM、工具函数等相关代码。
platforms
(不同平台的支持)
├── platforms # 平台相关代码
├── web # web 平台
├── compiler # 编译时相关
├── runtime # 运行时相关
├── serve