Skip to content
On this page

01_vue3源码的介绍及体验

一、源码目录结构介绍

vue3整个的项目结构是通过monorepo (单一代码库) 的形式来组织的。
所以说,vue3源码所有的模块都是在packages里面。

mono意为单一,repo意为仓库,是一种将多个项目代码存储在一个仓库里的软件开发策略。

这里呢,再浅浅说一下采用monorepo的好处:

monorepo最主要的好处是统一的工作流和Code Sharing

比如我想看一个package的代码、了解某段逻辑,不需要找它的repo,直接就在当前 repo;当某个需求要修改多个package时,不需要分别到各自的repo进行修改、测试、发版或者npm link,直接在当前repo 修改,统一测试、统一发版。只要搭建一套脚手架,就能管理(构建、测试、发布)多个package

代码重用将变得非常容易:由于所有的项目代码都集中于一个代码仓库,我们将很容易抽离出各个项目共用的业务组件或工具,并通过 TypeScriptLerna 或其他工具进行代码内引用;

依赖管理将变得非常简单:同理,由于项目之间的引用路径内化在同一个仓库之中,我们很容易追踪当某个项目的代码修改后,会影响到其他哪些项目。通过使用一些工具,我们将很容易地做到版本依赖管理和版本号自动升级。


下面就开始介绍vue3源码的核心结构,由下图开始:

01_vue3源码结构

1、compiler-sfc: 用来解析单文件组件,也就是.vue文件,因为.vue文件不能直接被浏览器解析,一般会借助webpackvue-loadertemplatescriptstyle 部分抽离出来,然后各个模块运行各自的解析器,单独解析,而解析工作都是由compiler-sfc模块实现的。

2、compiler-dom: 是在compiler-core的基础上进行的封装,是处理template的,会把template编译成一个render函数。

3、runtime-dom: 它就是基于runtime-core创建的以浏览器为目标的运行时,包括对原生DOM API、属性、样式、事件等的管理。

4、runtime-core: 核心运行时,包括虚拟DOM的渲染器、组件实现和一些全局的JavaScript API。

5、reactivity: 数据驱动是Vue.js的核心概念之一,响应式系统是实现数据驱动的前提。reactivity 包含了对响应式系统的实现,它是runtime-core包的依赖,也可是作为单独的包进行使用。

二、体验

先来体验一下compiler-sfc,此处借助rollup的打包功能,将sfc编译成一个js文件。

  1. 创建一个目录,初始化进行包管理

    shell
    # -y是生成默认package.json,省去回车
    npm init -y
  2. 首先安装一下compiler-sfc

    shell
    npm i @vue/compiler-sfc -s
  3. 再引入一下rollupvue官方提供的一个插件: roll-plugin-vue

    shell
    npm i rollup -D
    npm i rollup-plugin-vue -D
  4. 创建App.vuewebstorm的话,可以新建文件输入vbase-css,然后回车

    vue
    <template>
      <div>
        IamZJT
      </div>
    </template>
    
    <script>
    export default {
      setup() {
    
      }
    };
    </script>
    
    <style></style>
  5. 接下来创建rollup.config.js,进行roll-up的配置。

    ts
    import vue from 'rollup-plugin-vue';
    
    export default {
       input: './App.vue',
       plugin: [vue()],
       output: {
          name: 'vue',
          format: 'es',
          file: 'lib/mini-vue.esm.js'
       }
    }
  6. 配置package.jsonscripts

    json
    {
       "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "build": "rollup -c"
       }
    }
  7. 运行,至此,编译完成

    shell
    npm run build
    mini-vue.esm.js

以上,compiler-sfc已经体验过了,可以将.vue文件编译成js文件。

那么compiler-domcompiler-core又是用来解决什么问题的呢?

实际上是将template转成render函数。

.vue文件编译成js文件,和将template转成render函数,这是两个概念。

也就是说compiler-sfc是用到compiler-domcompiler-core这两个库的。

那是怎么将template转成render 函数的呢,这里有一个在线体验的网站:Vue 3 Template Explorer

vue
<div id="app">
  <div @click="() => console.log('IamZJT')" :id="name">{{ name }}</div>
    <h1 v-if="true">技术摸鱼</h1>
  <p>今天天气针不戳</p>
</div>
ts
// render函数
import {
  toDisplayString as _toDisplayString,
  createElementVNode as _createElementVNode,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
  createCommentVNode as _createCommentVNode
} from "vue"

// 这里`render`函数用到的这些函数,实际上都是属于vue的运行时的,都是在运行时里面去导出的。

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("div", { id: "app" }, [
    _createElementVNode("div", {
      onClick: () => _ctx.console.log('IamZJT'),
      id: _ctx.name
    }, _toDisplayString(_ctx.name), 9 /* TEXT, PROPS */, ["onClick", "id"]),
    true
      ? (_openBlock(), _createElementBlock("h1", { key: 0 }, "技术摸鱼"))
      : _createCommentVNode("v-if", true),
    _createElementVNode("p", null, "今天天气针不戳")
  ]))
}

综上来看,compiler-sfc依赖compiler-domcompiler-core两个模块,将template解析成render函数,然后再交给runtime来执行。

ps

这是一个 早起俱乐部

⭐️ 适合人群:所有想有所改变的人,可以先从早起半小时开始!抽出30分钟,从初心开始!!
⭐️ 没有任何其它意味,只是本人想寻找一起早起、志同道合的小伙伴。