Vue3源码解读--方向篇

一、前言
vue3文档地址、GitHub项目地址:

https://cn.vuejs.org/v2/api/

https://github1s.com/vuejs/vue-next/tree/3.2

    最近有小伙伴私聊广东靓仔,想系统的看vue3的源码,vue作为他主要的技术栈,想深入学习vue3,但是vue3太大了,无从下手。
    广东靓仔接下来会写几期直白的Vue3源码的文章~
二、如何本地调试vue3源码
    很多时候我们都是在本地调试vue3的源码,然后沿着调用链,一步一步的去梳理vue3的源码。
    把vue3项目拉到我们本地后,找到rollup.config.js文件,如下图所示:


然后在第85行开启sourcemap配置开启,


Source map是啥
简单理解:

Source map就是一个信息文件,里面储存着位置信息。转换后的代码的每一个位置,所对应的转换前的位置。

有了Source map,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,这样调试起来就会非常方便。

然后在你想调试的地方增加debugger即可

三、vue3有哪些不同
静态类型检查
我们都知道vue2是使用了Flow。

Flow是啥?

    Flow 是 Facebook 推出的,作为JavaScript 静态类型检查工具,它以非常小的成本对已有的 JavaScript 代码迁入,非常灵活。But对于一些复杂场景类型的检查,支持得并不好。
在vue2中,我们有时候看到过一些any有人就吐槽了。

Vue3 没用 Flow ,而是采用 TypeScript 重构了整个项目。
Why?

    TypeScript提供了更好的类型检查,它能支持复杂的类型推导;

    源码使用 TypeScript 编写,不再需要去单独维护 d.ts 文件,而且就整个 TypeScript 的生态来看,TypeScript 团队也是越做越好,TypeScript 本身保持着一定频率的迭代和更新,支持的 feature 也越来越多。

代码管理
Vue2 源码都是在src 目录下,如下图所示:



红色框住的:compiler、core、platforms、server、sfc、shared目录:

compiler:模板编译的相关代码
core:与平台无关的通用运行时代码
platforms:平台专有代码
server:服务端渲染的相关代码
sfc:.vue 单文件解析相关代码
shared: 共享工具代码
monorepo

Vue3 是通过 monorepo 的方式来维护,目录如下图所示:



    我们可以看到packages文件中放了功能不同的模块。下面我们拿其中compiler-core展开来看,如下图所示:





每个 package都有各自的 API、类型定义和测试。

Why?

广东靓仔认为是这样的:把每个模块拆分更细,那么它们之间的职责划分更明确,模块之间的依赖也更加清楚,方便我们阅读、理解和调试代码,很明显这样做是可以提高代码的可维护性。
还有更重要的一点,如果我们只是想使用这些包中的某一个,我们可以单独安装,而不需要安装整个vue。
Composition API
Vue3.0 提供了 Composition API,可以看到在语法进行了优化。
优化逻辑组织
将某个逻辑相关的代码全都放在一个函数里,这样就一目了然,看代码的时候我们就不需要切换目录。
逻辑复用
vue2使用mixins达到代码复用,用的人爽,后面维护的人,心里估计已经在拔刀了。
vue3我们可以用hook 函数,然后引入调用即可。
性能优化
vue3打包优化

   使用 tree-shaking 的技术,减少打包体积。Tree-shaking的本质是消除无用的js代码,也就是说我们在开发的时候不引入这个模块的所有代码,只引入需要的代码,打包后,只会包含我们引入的。
    tree-shaking 依赖 ES2015 模块语法的静态结构(即 import 和 export),通过编译阶段的静态分析,找到没有引入的模块并打上标记。
Tips:如果项目使用了 Transition、KeepAlive 等组件,也会被打包的~
优化编译过程

挂载过程,如下图:





编译过程,如下图:





    我们知道在数据劫持以及patch可以优化的地方比较多,vue3在编译阶段对静态模板的分析,编译生成了 Block tree。基于动态节点指令切割,每个区块内部的节点结构是固定的,以一个 Array 来追踪自身包含的动态节点。Vue 将 vnode 更新性能与动态内容的数量相关,很大程度提升性能。
   Vue 3.在编译阶段还对 Slot 的编译进行了优化、事件侦听函数做了缓存优化,运行时重写了 diff 算法...等等
new Proxy
     vue2数据劫持需要提前定义好key,vue3中使用Proxy,通过劫持整个对象 ,Object.defineProperty做不到的,它都可以实现了。vue3在getter 中递归找到真正的内部对象然后做响应式。这也是性能提升的一个环节。

四、分模块梳理源码
vue3挺大的一个项目,我们可以分模块来梳理:

provide inject
自定义事件
VNode
动态组件
双向绑定原理new Proxy
reactive源码
......等等
五、总结
    在我们阅读完官方文档后,我们一定会进行更深层次的学习,比如看下框架底层是如何运行的,以及源码的阅读。
    这里广东靓仔给下一些小建议:
在看源码前,我们先去官方文档复习下框架设计理念、源码分层设计
阅读下框架官方开发人员写的相关文章
借助框架的调用栈来进行源码的阅读,通过这个执行流程,我们就完整的对源码进行了一个初步的了解
接下来再对源码执行过程中涉及的所有函数逻辑梳理一遍

作者:广东靓仔


欢迎关注:前端早茶