当前位置: 首页 > 科技观察

从源码层面探秘Vue3初始化

时间:2023-03-22 01:04:27 科技观察

本期小编为大家带来:分析启动脚本,找到入口文件,看第一次编译流程,从源码层面剖析初始化细节。在开始本期之前,小编带大家回顾一下之前的知识点。还是从这张图开始,我们上一期提到Vue3.0源码中最核心的包就是以vue命名的文件包。这个包里面有3个依赖,其中runtime-dom和compiler-dom是一个明显的依赖,但是还有一个隐含的依赖叫做reactivitydependency,主要做一些响应式的处理。后面小编会带领大家重点关注这个依赖包的原理。其实真正的依赖是在runtime-core这个包里面,它真正告诉你createApp是怎么来的,它内部做了什么。小编整理了这里的逻辑关系图。createApp方法最终在createAppAPI中有一个工厂函数。这是扩展createApp的方法。扩展这个方法最重要的一点是让这??个功能更加通用。我们知道在createApp中传入一个render函数,但是对于createApp来说,它只是调用传入的参数,并不关心你对这个参数做了什么逻辑处理。我们真正能在实例上使用的方法是这个createAPIextension的source后面获取到的属性,比如componentmixinuse。看完文前内容,想必大家对createApp有了深刻的认识。接下来,我们将进入本章内容的核心部分。首先,我们将带领大家分析一下启动脚本,看看启动脚本是干什么的。"dev":"nodescripts/dev.js--sourcemap",这行代码想必大家都不陌生。这是我们启动项目的运行脚本。我们将从dev.js脚本文件开始。WeChat46b3d93f7c154ae5e1b95022c46eb57b.pngminimist是专门用来解析传入参数的。这是什么意思?当我们运行npmrundev命令时,我们实际运行的是nodescripts/dev.js,当传入如下路径时--或者--有时会被解析为第一个参数,否则会被打包成一个vue包。WeChat96a3eefa625cef34b030b68fe2353724.png从这张图也可以看出,dev-sfc部分使用的打包格式是esModule格式,在浏览器中会显示为type=module。那么现在我们知道了指令映射代码的含义,那么问题来了,接下来我们应该做什么呢?哈哈哈~如果对工程框架比较了解,我们还得看看打包工具的配置文件。看看你的entry入口文件和你的export输出文件打包后是怎么配置的。源码是rollup打包生成的,所以我们要浏览rollup.config.js配置文件。WeChatc8eb0ccf03ff5fb6b79d0ed338c01de1.png在配置文件中我们可以看到,所有获取的包目录都是从packages中获取的,通过process.env.TARGET对包名进行路径拼接会得到/packages/xxxWeChat024e26087aec3918dc0ecf425d3c7580.png这里是一些打包选项配置,例如CommonJsECMAScript格式。这里说一下iife格式,就是打包后生成匿名函数自调的格式。(()=>{})()WeChat465926fb4d72cd8107ca6bf763ffba32.png这里我们看到了真正的打包包名以runtime开头。这时候它会根据你的命令是否包含-fruntime-xxx格式生成两种映射。第一个是运行时打包,编译器没有初始化。装进去,二是装满。Wechece256bb4095f1e2a86c2e2321b505971.png于是,我们在packages/vue/index.ts路径下找到了包。在这个包中,有一个名为compileToFunction的编译函数。它真正的作用是解析模板中的innerHhtml,另外一个是生成一个render渲染函数,另外在这个函数中他会判断你传入的参数是不是字符串形式的模板,是否是另一种是dom,即支持的写法mount("

xxx")mount('#app')或mount(app)。WeChat98c822fa89560f875415a68ff6276a83.png到这里,在callStack中,真正的解释了compileToFunction是如何一步步变成渲染函数的。WeChat00a9bbcb59649cbbf8b1ce99b6c81d43.pngWechatIMG81.jpeg从上面我们可以看出,模板真的是传入的innterHtml。WeChat70bfdad15d56582ac1f31f3ea6ccab68.png经过浏览器调试,我们发现finishComponentSetup函数中调用了compileToFunction,template就是要解析的innerHTML。WeChat5f3653a52a450b5ece0d35a757cabe17.pngvue包中使用registerRuntimeCompiler注册了compileToFunction函数,就是在初始化需要编译的时候调用。这里原封不动的导出了runtime-dom,所以有vue->runtime-dom->runtime-core等依赖。WeChat581967ab4ceb37c6fefa2ed599d85bad.pngWeChat802ba115543725ce52877e96d64aa870.png后续流程为:createRenderer()=>baseCreateRenderer()=>createAppAPI(render,hydrate)=>createApp()app.mount()=>natch()>processComponent()=>mountComponent()这里我们主要研究mountComponent()挂载组件的作用。WechatIMG82.jpegWeChat280ea252a066a6ad52f94d5f261b9ba3.png这个函数中主要调用了两个函数,一个是createComponentInstance创建一个组件实例,一个是setupComponent初始化一个组件实例,从这个函数开始查找。WechatIMG86.jpegWechatIMG87.jpeg在这里我们可以看到组件初始化接收到的是一个setup,它对传入的不同方法做了各种处理,比如promise然后会在handleSetupResult()方法中处理setup的返回值。WechatIMG88.jpeg根据setup返回的不同类型进行处理,比如返回的是函数、对象或字符串。WechatIMG89.jpeg执行后会经过finishComponentSetup()方法。WeChatde62b32d0810ec4d669cb295a41fd91a.pngWeChat3cc852f1a9e27e9a71503075b277a1c8.png所以在这个函数中,它真正返回了一个兼容Vue2.0的render函数。至此,基本上所有初始化的逻辑都理顺了~总结一下本期内容,小编就从代码层面一步步告诉大家理解初始化过程,首先,执行哪个脚本文件是从package.json目录文件锁定,我们平时使用的打包工具,比如:webpackvite或者rollup,都会有一个配置文件xxx.config.js,从这个文件中,我们可以锁定entry的入口文件。确认入口文件后,我们可以找到各个包之间的依赖关系,根据依赖的包,一步步了解初始化的整体流程。对了,Vue3.0将在2022年2月7日正式成为默认版本,届时我们安装的vue将是3.x版本,Vue3的时代将正式开始!