返回

专栏第一篇-目录结构窥探

  因为 Vue 框架是在十多年前产生的一个开源前端框架,经过一些迭代修复,目前已经趋于稳定。

  Vue2框架在可维护性、性能、TypeScript支持等方面有一些痛点,所以尤雨溪推出了 Vue3版本。

  不过目前大部分公司因为成本等方面的原因,还是使用在 Vue2 版本,所以我们这个专栏就来探讨一下 Vue2 的源码部分。

一、非核心Vue源码目录大致结构

我们看的Vue源码版本2.7.16是Vue2的最新版本

我们打开Vue2的github源码地址。

可以看到其中有很多个目录文件,但是其实 Vue2 源码核心的都是在 src文件夹中的。

我们这章大概介绍一下除了 src 下面的一些目录,了解一下大体的作用是什么。

1.1 .github

该文件夹用于存放与 gitHub 相关的配置文件或者脚本。

1.2 benchmarks

该文件夹用于存放性能基准测试的相关文件和脚本。

性能基准测试是一种用来评估软件性能的方法,它通过模拟真实世界中的使用场景来测量软件在不同条件下的表现。

可以确保新功能不会降低框架的整体性能,同时也可以用来优化现有代码,使其更加高效。

1.3. compiler-sfc

该文件夹下的内容逻辑就可以协助 webpack进行解析处理单文件组件(SFC)。

通常我们开发时会借助webpack将vue文件转化为一个JS对象。

可以查看他的 index.js文件 发现实际上就是导出了@vue/compiler-sfc这个包。

1
module.exports = require('@vue/compiler-sfc')

1.4. dist

该文件夹为打包文件存放的地方。

1.5. examples

该文件夹用于存放示例应用程序或代码片段,目的是展示 Vue.js 的基本用法和功能。

1.6 packages

该文件夹主要用于组织 Vue.js 的各个子包或模块。

随着 Vue.js 项目的复杂度增加,将不同的功能模块拆分成独立的子包已经成为了一种常见的做法。

这样不仅有利于模块化开发,还能方便依赖管理和发布。

该目录下有三个目录。

1.6.1 compiler-sfc

该文件夹下的内容主要用于处理单文件组件。

1.6.2 server-renderer

该文件夹下的内容和服务端渲染相关的内容。

1.6.3 template-compiler

该文件夹下的内容存放模板编译相关的逻辑。

1.7 scripts

该文件夹主要用于存放各种自动化脚本。

这些脚本通常用于辅助项目的构建、测试、发布和其他开发任务。

1.8 src

该文件夹是存放 vue框架核心源码的地方。

1.9 test

该文件夹主要用于存放各种类型的测试文件,这些测试文件用于验证 Vue.js 框架的功能是否按预期工作。

1.10 types

该文件夹主要用于存放 TypeScript 类型定义文件。

这些类型定义文件为 Vue.js 提供了类型支持,使得在使用 Vue.js 时可以享受静态类型检查的好处,从而提高代码质量和开发效率。

1.11 .editorconfig

该文件用于指定编辑器应该遵循的一系列编码和格式化规则。

1.12 .git-blame-ignore-revs

该文件用于告诉 Git 在执行 git blame 命令时忽略某些特定的提交记录。

1.13 .gitignore

该文件用于指定 Git 应该忽略哪些文件或目录,即不将这些文件或目录纳入版本控制。

1.14 .prettierrc

该文件用于配置 Prettier。

Prettier是一个流行的代码格式化工具,旨在帮助开发者保持代码风格的一致性。

Prettier 可以自动格式化代码,使其符合预设的编码规范,从而提高代码的可读性和一致性。

1.15 BACKERS.md

该文件主要用于记录和支持 Vue.js 项目的赞助者或贡献者。

这份文件通常列出了那些通过资金或其他形式支持 Vue.js 发展的个人或组织。

1.16 CHANGELOG.md

该文件主要用于记录项目的版本变更历史,包括每个版本的新增功能、改进、修复的错误以及其他重要的变更信息。

1.17 LICENSE

该文件用来定义和声明项目使用的许可协议的文件

1.18 README.md

该文件为项目的入口文档文件。

文件提供了关于项目的概述、安装步骤、使用方法、贡献指南等关键信息。

1.19 api-extractor.json

该文件用于配置 API Extractor 工具(这是一种用于生成 TypeScript 类型定义文档和 API 报告的工具)

API Extractor 通常用于大型 TypeScript 项目中,帮助开发者生成详细的 API 文档,并确保类型定义的一致性和准确性。

1.20 api-extractor.tsconfig.json

该文件用于配置 TypeScript 编译选项,以配合 API Extractor 工具生成 API 文档和类型定义文件。

这个文件通常包含了一些特定的 TypeScript 配置,确保 API Extractor 能够正确地解析和处理源代码。

1.21 package.json

该文件是项目的核心配置文件,用于描述项目的元数据以及项目依赖关系和构建脚本。

1.22 pnpm-lock.yaml

该文件是由 pnpm 包管理器生成的锁定文件。

用于记录项目中所有依赖项的具体版本信息,以及它们是如何被安装的。

pnpm 是一种替代 npm 和 yarn 的高性能包管理器,它具有更快的速度和更少的磁盘空间占用。

1.23 pnpm-workspace.yaml

该文件用于配置 pnpm 工作区(workspace)。

pnpm 支持多项目的工作区模式,这种模式允许多个相关项目共享依赖,并且可以方便地管理这些项目的依赖关系和构建流程。

1.24 tsconfig.json

该文件是 TypeScript 编译配置文件,用于定义 TypeScript 编译器在编译源代码时应遵循的选项和规则。

1.25 vitest.config.ts

该文件用于配置 Vitest 的测试框架配置文件。

Vitest 是一个现代化的 JavaScript 和 TypeScript 测试框架,它提供了快速的测试运行速度和丰富的功能集,适用于前端和后端开发。

二、src目录下有什么?

上一章节我们简单介绍了一下非 src文件夹下面的一些文件内容。

这些都是在一个工程化的框架项目中必不可少的部分。

那么本节的内容就是看下 src 文件夹下包含哪些内容。

下面这个目录结构去除了 ts相关的声明文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
src
├─shared
| ├─constants.ts
| └util.ts
├─platforms
| ├─web
| | ├─entry-compiler.ts
| | ├─entry-runtime-esm.ts
| | ├─entry-runtime-with-compiler-esm.ts
| | ├─entry-runtime-with-compiler.ts
| | ├─entry-runtime.ts
| | ├─runtime-with-compiler.ts
| | ├─util
| | | ├─attrs.ts
| | | ├─class.ts
| | | ├─compat.ts
| | | ├─element.ts
| | | ├─index.ts
| | | └style.ts
| | ├─runtime
| | | ├─class-util.ts
| | | ├─index.ts
| | | ├─node-ops.ts
| | | ├─patch.ts
| | | ├─transition-util.ts
| | | ├─modules
| | | | ├─attrs.ts
| | | | ├─class.ts
| | | | ├─dom-props.ts
| | | | ├─events.ts
| | | | ├─index.ts
| | | | ├─style.ts
| | | | └transition.ts
| | | ├─directives
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └show.ts
| | | ├─components
| | | | ├─index.ts
| | | | ├─transition-group.ts
| | | | └transition.ts
| | ├─compiler
| | | ├─index.ts
| | | ├─options.ts
| | | ├─util.ts
| | | ├─modules
| | | | ├─class.ts
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └style.ts
| | | ├─directives
| | | | ├─html.ts
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └text.ts
├─core
| ├─config.ts
| ├─index.ts
| ├─vdom
| | ├─create-component.ts
| | ├─create-element.ts
| | ├─create-functional-component.ts
| | ├─patch.ts
| | ├─vnode.ts
| | ├─modules
| | | ├─directives.ts
| | | ├─index.ts
| | | └template-ref.ts
| | ├─helpers
| | | ├─extract-props.ts
| | | ├─get-first-component-child.ts
| | | ├─index.ts
| | | ├─is-async-placeholder.ts
| | | ├─merge-hook.ts
| | | ├─normalize-children.ts
| | | ├─normalize-scoped-slots.ts
| | | ├─resolve-async-component.ts
| | | └update-listeners.ts
| ├─util
| | ├─debug.ts
| | ├─env.ts
| | ├─error.ts
| | ├─index.ts
| | ├─lang.ts
| | ├─next-tick.ts
| | ├─options.ts
| | ├─perf.ts
| | └props.ts
| ├─observer
| | ├─array.ts
| | ├─dep.ts
| | ├─index.ts
| | ├─scheduler.ts
| | ├─traverse.ts
| | └watcher.ts
| ├─instance
| | ├─events.ts
| | ├─index.ts
| | ├─init.ts
| | ├─inject.ts
| | ├─lifecycle.ts
| | ├─proxy.ts
| | ├─render.ts
| | ├─state.ts
| | ├─render-helpers
| | | ├─bind-dynamic-keys.ts
| | | ├─bind-object-listeners.ts
| | | ├─bind-object-props.ts
| | | ├─check-keycodes.ts
| | | ├─index.ts
| | | ├─render-list.ts
| | | ├─render-slot.ts
| | | ├─render-static.ts
| | | ├─resolve-filter.ts
| | | ├─resolve-scoped-slots.ts
| | | └resolve-slots.ts
| ├─global-api
| | ├─assets.ts
| | ├─extend.ts
| | ├─index.ts
| | ├─mixin.ts
| | └use.ts
| ├─components
| | ├─index.ts
| | └keep-alive.ts
├─compiler
| ├─codeframe.ts
| ├─create-compiler.ts
| ├─error-detector.ts
| ├─helpers.ts
| ├─index.ts
| ├─optimizer.ts
| ├─to-function.ts
| ├─parser
| | ├─entity-decoder.ts
| | ├─filter-parser.ts
| | ├─html-parser.ts
| | ├─index.ts
| | └text-parser.ts
| ├─directives
| | ├─bind.ts
| | ├─index.ts
| | ├─model.ts
| | └on.ts
| ├─codegen
| | ├─events.ts
| | └index.ts

三、shared文件夹

1
2
3
4
src
├─shared
| ├─constants.ts
| └util.ts

这个文件夹包含了一些在不同环境下都需要共享的工具函数或者常量。

这个工具函数与平台无关。

既可以在客户端使用,也可以在服务端使用,因为它们不依赖于任何特定的环境特性(例如 DOM)。

  • constants.ts文件中定义了一些在整个框架内频繁使用的常量,比如特殊的字符串标识符、配置键名等。
  • util.ts文件中定义了一些基础的工具函数,比如 isString、isObject和其他一些常用的功能,如深拷贝、警告输出等。

这些文件的主要目的是为了提高代码的可维护性和复用性。

通过将这些功能抽象出来,Vue.js 能够保持核心逻辑的简洁,并且确保不同部分之间的兼容性。

这样做的好处是减少了重复代码,使得代码更容易理解和维护。

四、platforms文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
src
├─platforms
| ├─web
| | ├─entry-compiler.ts
| | ├─entry-runtime-esm.ts
| | ├─entry-runtime-with-compiler-esm.ts
| | ├─entry-runtime-with-compiler.ts
| | ├─entry-runtime.ts
| | ├─runtime-with-compiler.ts
| | ├─util
| | | ├─attrs.ts
| | | ├─class.ts
| | | ├─compat.ts
| | | ├─element.ts
| | | ├─index.ts
| | | └style.ts
| | ├─runtime
| | | ├─class-util.ts
| | | ├─index.ts
| | | ├─node-ops.ts
| | | ├─patch.ts
| | | ├─transition-util.ts
| | | ├─modules
| | | | ├─attrs.ts
| | | | ├─class.ts
| | | | ├─dom-props.ts
| | | | ├─events.ts
| | | | ├─index.ts
| | | | ├─style.ts
| | | | └transition.ts
| | | ├─directives
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └show.ts
| | | ├─components
| | | | ├─index.ts
| | | | ├─transition-group.ts
| | | | └transition.ts
| | ├─compiler
| | | ├─index.ts
| | | ├─options.ts
| | | ├─util.ts
| | | ├─modules
| | | | ├─class.ts
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └style.ts
| | | ├─directives
| | | | ├─html.ts
| | | | ├─index.ts
| | | | ├─model.ts
| | | | └text.ts

4.1 为什么会有这么一个platforms目录呢?

platforms 翻译成中文表示“平台“。

vue作为一个跨平台的框架,不仅支持传统的web浏览器环境,还支持其他平台,如服务器渲染(SSR),甚至是非浏览器环境。

因此,将 Web 平台相关的代码单独放在一个目录中,有助于保持代码的清晰度和可维护性。

Web平台有许多特定的功,比如 DOM操作、CSS动画、事件处理等。这些功能在 Vue的 Web版本中是必需的,但是在其他平台上则不一定适用。将这些代码组织在一起,可以确保它们只在 Web平台上生效,而不会影响到其他平台的构建。

当然目前仅仅只有一个web平台,所以平台下只有一个 web目录。

4.2 几个入口文件

entry-*文件主要用于定义不同构建配置下的入口点。

web目录下有entry-compiler.tsentry-runtime-esm.tsentry-runtime-with-compiler-esm.tsentry-runtime-with-compilerentry-runtime.ts五个入口文件。

在vue源码scripts/config.js中有打包相关的配置,其中就利用了这几个入口文件。

4.2.1 entry-compiler.ts

该文件是一个提供编译 html 模板相关接口的模块,通常用于为 Vue 编写的构建插件,比如 vue-loader。

1
2
3
4
5
6
7
8
9
10
11
// scripts/config.js
let builds = {
compiler: {
entry: resolve('web/entry-compiler.ts'),
dest: resolve('packages/template-compiler/build.js'),
format: 'cjs',
external: Object.keys(
require('../packages/template-compiler/package.json').dependencies
)
},
}

4.2.2 entry-runtime.ts & entry-runtime-esm.ts

这两个文件都用于构建仅包含运行时的文件,不具备编译 html 模板功能。区别是一个是 esm格式,一个不是。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// scripts/config.js
let builds = {
'runtime-esm': {
entry: resolve('web/entry-runtime-esm.ts'),
dest: resolve('dist/vue.runtime.esm.js'),
format: 'es',
banner
},
'runtime-prod': {
entry: resolve('web/entry-runtime.ts'),
dest: resolve('dist/vue.runtime.min.js'),
format: 'umd',
env: 'production',
banner
},
}

4.2.3 entry-runtime-with-compiler.ts & entry-runtime-with-compiler-esm.ts

这两个文件都用于构建同时包含编译器和运行时的全功能文件。

区别是一个是 esm格式,一个不是。

下面的full-cjs-prod可以看出来这个全版本,有 vue的全部功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// scripts/config.js
let builds = {
'full-cjs-prod': {
entry: resolve('web/entry-runtime-with-compiler.ts'),
dest: resolve('dist/vue.common.prod.js'),
format: 'cjs',
env: 'production',
alias: { he: './entity-decoder' },
banner
},
'full-esm-browser-prod': {
entry: resolve('web/entry-runtime-with-compiler-esm.ts'),
dest: resolve('dist/vue.esm.browser.min.js'),
format: 'es',
transpile: false,
env: 'production',
alias: { he: './entity-decoder' },
banner
},
}

4.3 runtime-with-compiler.ts

之前我们了解到 Vue分为 runtime 和 compiler两个部分。

而 runtime-with-compiler.ts文件就是既有 runtime部分 也有 compiler部分。

上面的entry-runtime-with-compiler.tsentry-runtime-with-compiler-esm.ts就是基于这个文件进行打包的。只是分别扩展了vue的一些功能。

4.4 util目录

该目录包含了 Vue在 Web平台上常用的工具函数和使用工具。

这些工具主要用于处理与 Web平台相关的各种细节。

4.5 runtime目录

4.5.1 components目录

该目录下存放着 vue web平台中使用的组件如 transition、transition-group组件等,借助这些组件可以实现过渡动画。

4.5.2 directives目录

该目录下的主要存放是 vue的内部指令文件,如v-model、v-show指令。

4.5.3 modules目录

该目录下的主要存放的是vue在 web平台上常见的 DOM操作和特性处理。

4.5.3.1 attrs.ts

这个文件实现了处理元素属性的模块,它负责更新和管理元素的属性。例如,当数据模型中的属性值发生变化时,需要更新 DOM 中相应的属性值。

4.5.3.2 class.ts

这个文件实现了处理元素类的模块,它负责更新和管理元素的类名。例如,根据数据模型中的条件动态添加或移除类名。

4.5.3.3 dom-props.ts

这个文件实现了处理 DOM 属性的模块,它负责同步和更新 DOM 属性,如 value, checked 等。这在处理表单控件时尤为重要。

4.5.3.4 events.ts

这个文件实现了处理事件绑定的模块,它负责在 DOM 元素上添加、更新和移除事件监听器。这使得 Vue.js 可以响应用户的交互行为,并触发相应的事件处理函数。

4.5.3.5 style.ts

这个文件实现了处理内联样式的模块,它负责更新和管理元素的内联样式。例如,根据数据模型中的条件动态设置或移除内联样式。

4.5.3.6 transition.ts

这个文件实现了处理过渡动画的模块,它负责应用过渡类,管理过渡状态,并确保过渡效果正确地应用于元素。

4.5.4 transition-util.ts

该文件包含了 Vue.js 在 Web 平台上与过渡动画相关的实用工具函数。

这些工具函数为 <transition><transition-group> 组件提供了底层的支持,使得 Vue.js 能够管理和控制元素的过渡效果。

4.5.5 patch.ts

该文件是 Vue.js 在 Web 平台上负责 DOM 更新的核心模块。

这个文件定义了 patch 函数,它是 Vue.js 渲染引擎的关键部分之一,用于将虚拟 DOM(Virtual DOM)更新到实际的 DOM 上。

他实际上引用了core/vdom/patch目录下的 createPatchFunction函数。

4.5.6 node-ops.ts

该文件包含了 Vue.js 在 Web 平台上进行 DOM 操作的具体实现。

这个文件定义了一组方法,这些方法是 Vue.js 渲染引擎在更新 DOM 时使用的具体操作。如添加节点、删除节点等。

4.5.7 class-util.ts

该文件包含了 vue 在 web平台上与元素类相关的使用工具函数。

这些工具函数用于处理元素的类名,包括添加、删除和切换类名等操作。

4.6 compiler目录

该目录包含了 Vue.js 在 Web 平台上进行模板编译的相关实现。

这个目录中的文件和模块负责将 Vue 模板字符串转换为可以被 Vue 渲染引擎执行的渲染函数。

其中 directives目录下的文件 定义了一些内置指令如v-html、v-text

modules目录中存放了对应处理模板编译时需要的一些通用处理方法。

其余文件为通用工具等。

五、core文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
src
├─core
| ├─config.ts
| ├─index.ts
| ├─vdom
| | ├─create-component.ts
| | ├─create-element.ts
| | ├─create-functional-component.ts
| | ├─patch.ts
| | ├─vnode.ts
| | ├─modules
| | | ├─directives.ts
| | | ├─index.ts
| | | └template-ref.ts
| | ├─helpers
| | | ├─extract-props.ts
| | | ├─get-first-component-child.ts
| | | ├─index.ts
| | | ├─is-async-placeholder.ts
| | | ├─merge-hook.ts
| | | ├─normalize-children.ts
| | | ├─normalize-scoped-slots.ts
| | | ├─resolve-async-component.ts
| | | └update-listeners.ts
| ├─util
| | ├─debug.ts
| | ├─env.ts
| | ├─error.ts
| | ├─index.ts
| | ├─lang.ts
| | ├─next-tick.ts
| | ├─options.ts
| | ├─perf.ts
| | └props.ts
| ├─observer
| | ├─array.ts
| | ├─dep.ts
| | ├─index.ts
| | ├─scheduler.ts
| | ├─traverse.ts
| | └watcher.ts
| ├─instance
| | ├─events.ts
| | ├─index.ts
| | ├─init.ts
| | ├─inject.ts
| | ├─lifecycle.ts
| | ├─proxy.ts
| | ├─render.ts
| | ├─state.ts
| | ├─render-helpers
| | | ├─bind-dynamic-keys.ts
| | | ├─bind-object-listeners.ts
| | | ├─bind-object-props.ts
| | | ├─check-keycodes.ts
| | | ├─index.ts
| | | ├─render-list.ts
| | | ├─render-slot.ts
| | | ├─render-static.ts
| | | ├─resolve-filter.ts
| | | ├─resolve-scoped-slots.ts
| | | └resolve-slots.ts
| ├─global-api
| | ├─assets.ts
| | ├─extend.ts
| | ├─index.ts
| | ├─mixin.ts
| | └use.ts
| ├─components
| | ├─index.ts
| | └keep-alive.ts

core文件夹是存储这 vue的核心逻辑。

5.1 components目录

该目录下存放了一些内置组件如 keep-alive。

5.2 global-api目录

该目录包含了 Vue.js在核心层面提供的全局 API的实现。

Vue.mixinVue.useVue.extend等。

5.3 instance目录

该目录包含了 vue实例相关的主要实现。

其中:render.js负责渲染相关的逻辑lifecycle.js负责管理 vue实例的生命周期钩子events.js负责处理 vue实例上的事件state.js负责管理 vue实例的数据状态等。

5.4 observe目录

该目录包含了 Vue.js 中用于实现响应式系统的核心模块。

这部分代码负责将数据对象转换为可观察的对象,使得数据的变化能够被追踪,并自动更新依赖于该数据的视图。

5.5 vdom目录

该目录包含了Vue.js 处理虚拟 DOM (Virtual DOM) 的相关实现。

虚拟 DOM 是 Vue.js 渲染机制的核心部分,它通过内存中的 JavaScript 对象来表示真实的 DOM 节点。

六、compiler文件夹

该目录存放了vue模板编译的相关内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
src
├─compiler
| ├─codeframe.ts
| ├─create-compiler.ts
| ├─error-detector.ts
| ├─helpers.ts
| ├─index.ts
| ├─optimizer.ts
| ├─to-function.ts
| ├─parser
| | ├─entity-decoder.ts
| | ├─filter-parser.ts
| | ├─html-parser.ts
| | ├─index.ts
| | └text-parser.ts
| ├─directives
| | ├─bind.ts
| | ├─index.ts
| | ├─model.ts
| | └on.ts
| ├─codegen
| | ├─events.ts
| | └index.ts

七、总结

我们这章大概的介绍了 vue的大体目录结构。


本站总访问量