Vue3小菜:架构及版本对比

67 阅读5分钟

前言

整体设计思想

  • 模块拆分,Vue3中模块与模块之间耦合度较低,可以独立使用
  • 按需引入,再配合构建工具的tree-shaking,可以大幅度减少打包体积
  • 重写API
  • 自定义渲染器,扩展能力强。
  • 虚拟Dom思想,比较新旧虚拟节点,找到变化再更新diff
  • 区分编译时和运行时
    • 编译时:模板语法 => render函数 => 虚拟DOM
    • 运行时:将虚拟DOM转为真实DOM
  • 采用typescript开发
  • 依然保留vue2的逻辑

Vue3&Vue2对比

  • 源码架构
    • vue3:更注重模块的拆分,源码采用Monorepo的方式管理,将模块拆分到package目录下,各模块自成一个npm包,模块间耦合度低,模块可独立使用。
    • vue2:源码处于同一个包中,后续迭代时只能在其基础上开发,如weex、mp-vue,代码结构冗余。
  • 类型检测选择:
    • vue3:TS,代码提示强,强类型检测。
    • vue2:flow,有些类型无法推断出来。
  • 性能:
    • vue3:全ESModule开发,支持tree-shaking,代码打包体积较好。
    • vue2:配置生成文件,无法准确推断模块是否使用。
  • API
    • Vue3:composition-api
    • Vue2:option-api
  • 渲染器
    • Vue3:自定义渲染器,扩展能力强。
    • Vue2:统一渲染器
  • 开发方式
    • Vue3:ts+ESModule
    • Vue2:js+传统模块化

Vue3代码优化

  • Vue3采用Proxy替代Vue2的defineProperty
    • defineProperty的缺陷:遍历对象所有属性、新增删除属性无法监听到。
  • 模板编译优化
    • 编译时生成Block tree,可以对动态节点进行收集,可以减少比较,并且采用patchFlag标记动态节点。
  • 采用CompositionApi组织功能
    • 解决反复跳转开发,优化复用逻辑(mixin带来的数据源不清晰、命名冲突问题)。
    • 相比OptionApi,类型推断更方便。
  • 增加了Fragment、Teleport、Suspense等组件。

Vue3架构

环境区分

  • Vue将代码运行环境区分为运行时编译时,也有运行时+编译时
  • 对于开发者而言:
    • 运行时只能执行使用render渲染虚拟节点。
    • 编译时只能通过template将模板编译成render才能运行。
    • 默认开发时是运行时+编译时的环境。
    • 生产环境可以只部署编译时的代码,减少编译体积。

Monorepo架构

简介

  • 是管理项目代码的一种思路/方式,指在一个项目仓库 (git-repo) 中管理多个模块/包 (npm-package),不同于常见的每个模块建一个git-repo
  • 目前不少大型开源项目采用了这种方式,如Babel、React、Vue等。monorepo管理代码只要搭建一套脚手架,就能管理(构建、测试、发布)多个package
  • 在前端使用角度来看,monorepo就是把多个工程放到一个git仓库中进行管理,因此他们可以共享同一套构建流程、代码规范也可以做到统一,特别是如果存在模块间的相互引用的情况,查看代码、修改bug、调试等会更加方便。
  • Monorepo里面的每个功能模块,则是像我们玩的乐高积木一样,有标准的接口,即使从这个项目中拆离出去,也能使用。
  • pnpm&monorepo

优点

  • 代码复用非常简单【共用公共依赖】
  • 简化依赖管理【同级目录方便相互引用】
  • 原子提交能让重构全局特性更容易【一个git】
  • 跨组合作更方便【各依赖间无逻辑关联性,只有引用关联】

pnpm

  • 一个较新的包管理工具,通过软硬连接的方式共用相同的依赖。
    • 优点:
      • 减小依赖包体积,且下载过的包会被缓存至本地磁盘,二次下载更快。
      • 更加优雅的处理幽灵依赖的问题(依赖A的依赖B被直接使用,若后续依赖A不再使用依赖B,则项目报错)。
    • 缺点:需要定时清空磁盘中的缓存依赖,避免过大。

Vue3中的Monorepo环境

  • 基于pnpm搭建的Monorepo项目仓库。
  • 搭建思路
    1. 初始化pnpm init -y
    2. 配置公共目录(workspace)。
    3. 新建npm配置文件.npmrc,配置幽灵依赖删除。
    • // .npmrc
      // 幽灵依赖--将依赖A中的依赖同步到node_module下,避免以后依赖A中的依赖发生改变,导致无法察觉的bug
      shamefully-hoist = true
      
    1. 在公共目录下新增子仓库(packages下)
    2. 初始化子仓库,则子仓库们可共用相同的依赖,且有自己的依赖,且两两解耦。

Vue3组成与架构一切基于组件

  • reactivity :核心包,响应式系统
  • runtime-core :与平台无关的运行时核心(扩展包,可根据平台扩展出对应的API,自定义渲染器)。
    • createRenderer:根据平台使用核心包core,创建出对应的渲染器render
      • render -- 渲染器把接收到的虚拟DOM,转换成真实DOM并渲染至宿主元素
        • 本质是使用patch
      • createApp:createApp(render,hydrate) -- 创建实例
      • hydrate -- SSR,服务端直接将vnode生成为一个html
  • runtime-dom :针对浏览器的运行时。包括DOM API,属性,事件处理等。
  • runtime-test :用于测试;
  • server-renderer :用于服务器端渲染;
  • compiler-core :与平台无关的编译器核心;
  • compiler-dom :针对浏览器的编译模块;
  • compiler-ssr :针对服务端染的编译模块;
  • compiler-sfc :针对单文件解析;
  • size-check :用来测试代码体积
  • template-explorer : 用于调试编译器输出的开发工具
  • shared :多个包之间共享的内容
  • vue :完整版本包括运行时和编译器
  • 2022-12-17-15-37-51.png
  • 2023-02-14-11-19-45.png
  • 2023-02-14-11-20-57.png

环境搭建

  • 搭建monorepo[模块共享]

      1. pnpm init -y
      2. mkdir packages
      3. vi .npmrc
      4. pnpm install vue -w
        1. -w => workspace
    
  • 搭建环境pnpm install

    • ts => typescript
    • es => esbuild[速度很快的es模块转换]
      • 2022-06-07-20-35-26.png
    • 获取命令行参数框架 => minimist
      • scripts/*
  • 图例:2023-02-14-16-16-26.png