社区编辑申请
注册/登录
源码层面探索Vue3初始化
开发 前端
我们通常使用的打包工具如:webpack vite 或者 rollup 之类的都会有一个配置文件 xxx.config.js 从这个文件中我们就能锁定 entry 的入口文件,通过确定入口文件之后我们就能找到各个包之间的依赖关系,根据依赖包,一步步深挖理解初始化的整体流程。

本期内容小编将给大家带来:

  • 分析启动脚本
  • 查找入口文件

看看首次编译过程,从源码层面解析初始化细节

在我们开始这期内容之前,小编先带领大家回顾一下上期的知识点。

还是从这张图开始,在上期内容中我们谈到,Vue3.0的源码中最为核心的包就是叫做以 vue命名的文件包,在这个包内有三个依赖关系,其中 runtime-dom 和 compiler-dom 是明显的依赖关系,但其中还有一个隐性的依赖叫做reactivity 的依赖,这里面主要是做响应式的一些处理,后期小编会带领大家着重探讨这个依赖包的原理,而其实真正的依赖在 runtime-core 这个包里,这个包才是真正告诉你createApp 是怎么由来的,内部又做了哪些事情。

小编这里梳理了一下逻辑关系图,createApp 这个方法最终在 createAppAPI 内部有一个工厂函数在这里得到了一次扩展 createApp 的方法,扩展此方法最为重要的一点就是为了让这个函数变得更加通用,我们知道在 createApp 里面传入一个 render 函数,但是对于 createApp 来说它只管调用传入进来的参数,而并不关心你这个参数做了哪些的逻辑处理,真正我们能够使用实例上的方法就是来源这个 createAPI 扩展之后得到的属性,例如 component mixin use。

正文经过之前的内容回顾,想必大家对 createApp已经有了深刻的了解,接下来将进入到本章内容的核心部分,首先带领大家分析启动脚本,看看启动脚本都做了哪些事情。

"dev": "node scripts/dev.js --sourcemap",

这行代码想必大家应该都不陌生吧,这就是我们启动项目的运行脚本我们就要从 dev.js 这个脚本文件开始下手。

WeChat46b3d93f7c154ae5e1b95022c46eb57b.png

minimist 是专门用来解析传进来的参数,什么意思呢?当我们在运行 npm run dev 这行命令的时候实际上是运行 node scripts/dev.js 当后面的路径传入 -- 或者 - 的时候会被解析成为第一个参数,否则会打包成 vue 的包。

WeChat96a3eefa625cef34b030b68fe2353724.png

在这张图中也能看出 dev-sfc 部分使用的打包格式为 esModule 格式,在浏览器中则会以type=module 出现。那么我么现在知道指令映射的代码中的含义了,那么问题来了下一步我们该干什么呢?哈哈哈~ 如果对工程化的框架比较了解的话,我们就要看看打包工具的配置文件,看看打包过后你的 entry 入口文件和你的export 打包后输出文件是怎样配置的,在源码中使用的是 rollup 打包生成的,所以我们要浏览一下 rollup.config.js 这个配置文件。

WeChatc8eb0ccf03ff5fb6b79d0ed338c01de1.png

在配置系文件中我们就可以看到,所有获取包目录都是从 packages 中得来的,通过process.env.TARGET 进行包名的路径拼接,就会得到 /packages/xxx

WeChat024e26087aec3918dc0ecf425d3c7580.png

这里就是要配置的一些打包选项,例如CommonJs ECMAScript 格式,这里讲一下 iife格式,就是打包后生成一个匿名函数自调的格式,(()=>{})()

WeChat465926fb4d72cd8107ca6bf763ffba32.png

这里我们看到真正打包的是以 runtime 开头的包名称,这时候他会根据你的指令中是否包含 -f runtime-xxx 这种格式的映射,生成两种第一个是运行时打包,没有在初始化的时候把编译器打包进去,第二个则是全量打包。

WeChatee256bb4095f1e2a86c2e2321b505971.png

所以,我们就找到了在 packages/vue/index.ts这个路径下的包,在这个包里面有一个叫做compileToFunction 编译函数其真正的作用就是一个是解析 template 中的 innerHhtml,另一个就是生成一个 render 渲染函数,另外,在这个函数中他会判断你传进来的参数是不是以字符串形式的模板另外一个是不是 dom,就是说支持的写法 mount("< div>xxx") mount('#app') 或者 mount(app)。

WeChat98c822fa89560f875415a68ff6276a83.png

这里在 callStack 中就真正的解析了compileToFunction 是如何一步一步的变成渲染函数。

WeChat00a9bbcb59649cbbf8b1ce99b6c81d43.png

WechatIMG81.jpeg

从这个上面我们就看出,template 真正就是传入的 innterHtml。

WeChat70bfdad15d56582ac1f31f3ea6ccab68.png

通过浏览器调试后我们就得出compileToFunction 是在 finishComponentSetup这个函数中调用的,而 template 就是要解析的innerHTML。

WeChat5f3653a52a450b5ece0d35a757cabe17.png

vue包中使用 registerRuntimeCompiler 将 compileToFunction 这个函数注册,这是为了初始化需要编译时能够调用它。这里原封不动导出 runtime-dom,因此有了vue -> runtime-dom -> runtime-core这样的依赖关系。

WeChat581967ab4ceb37c6fefa2ed599d85bad.png

WeChat802ba115543725ce52877e96d64aa870.png

随后的流程就是:

createRenderer() => baseCreateRenderer() =>

createAppAPI(render, hydrate) => createApp()

app.mount() => render() => patch(n1, n2) =>

processComponent() => mountComponent()

这里我们主要研究一下 mountComponent() 挂载组件做了哪些事情。

WechatIMG82.jpeg

WeChat280ea252a066a6ad52f94d5f261b9ba3.png

在这个函数内主要有两个函数调用,一个是createComponentInstance 创建组件实例,另一个是 setupComponent 初始化组件实例,从这个函数开始找寻。

WechatIMG86.jpeg

WechatIMG87.jpeg

在这里我们就看到组件初始化接收的就是一个setup 这块对传入不同方法做了各种处理,例如promise随后会在 handleSetupResult() 这个方法内处理 setup 的返回值。

WechatIMG88.jpeg

根据 setup 返回不同的类型作出处理,比如 返回的是一个函数,对象或者字符串之类的。

WechatIMG89.jpeg

执行完毕后都会走 finishComponentSetup() 这个方法。

WeChatde62b32d0810ec4d669cb295a41fd91a.png

WeChat3cc852f1a9e27e9a71503075b277a1c8.png

所以在这个函数内真正的是 返回一个 render 函数,并且兼容 Vue2.0 的方法。

到这里,基本上初始化所有的逻辑就理顺啦~

总结

这期内容小编就告诉大家从代码的层面一步步的深入了解初始化过程,首先是从 package.json目录文件中锁定执行的哪个脚本文件,我们通常使用的打包工具如:webpack vite 或者 rollup之类的都会有一个配置文件 xxx.config.js 从这个文件中我们就能锁定 entry 的入口文件,通过确定入口文件之后我们就能找到各个包之间的依赖关系,根据依赖包,一步步深挖理解初始化的整体流程。

顺便说一句 Vue3.0 在2022年2月7日将正式成为默认版本,届时我们安装的 vue 将会是3.x这个版本,属于Vue3的时代将正式开启!


责任编辑:武晓燕 来源: 村长学前端
相关推荐

2022-06-15 11:51:14

Vue3开发避坑

2021-12-13 00:54:14

2021-07-29 12:05:18

2021-12-12 18:31:35

2021-09-22 07:57:23

2022-02-06 22:13:47

2020-09-17 07:08:04

TypescriptVue3前端

2021-09-27 06:29:47

2021-03-22 10:05:25

2020-10-28 08:26:23

Vue源码开发

2020-08-25 09:50:35

Vue3.0命令前端

2016-11-03 13:19:38

vue.jsjavascript前端

2020-10-28 08:06:09

Vue3框架数据

2021-10-21 06:52:17

2021-03-08 00:08:29

Vue应用挂载

2021-04-02 10:30:18

Vue3.0前端代码

2021-02-22 21:49:33

Vue动态组件

同话题下的热门内容

程序员不得不知道的 API 接口常识使用 Vite 和 TypeScript 带你从零打造一个属于自己的 Vue3 组件库TestOps完全手册:工作流、生命周期、团队和流程字节的前端监控 SDK 是怎样设计的不要在 Python 中使用循环,这些方法其实更棒!你需要知道的TypeScript高级类型哪种编程语言最适合开发网页抓取工具?Hooks时代,如何写出高质量的react和vue组件?

编辑推荐

太厉害了,终于有人能把TCP/IP协议讲的明明白白了!牛人5次面试腾讯不成功的经验HBase原理–所有Region切分的细节都在这里了Javascript如何监听页面刷新和关闭事件如何搭建一个HTTPS服务端
我收藏的内容
点赞
收藏

51CTO技术栈公众号