Vue3 源码内参<一>手写mini-vue3前置准备

1,396 阅读3分钟

实现 mini-vue 前置准备

前言

本节代码演示地址,配合源码食用更开胃噢!

手把手实现 mini-vue,实现之前要了解一些前置知识:

  • Vue3 新特性
  • TDD 测试驱动开发

Vue3 新特性

  • 性能比 Vue 2.x 快 2 倍左右
  • Tree shaking 按需编译,静态节点标记、事件侦听缓存等
  • Fragment、Teleport、suspense 更先进的组件
  • Composition 组合 API
  • Vue3 使用的是 proxy 数据代理,而 Vue2 是使用 Object.defineProperty 进行数据劫持
  • 更好的 Ts 支持
  • Custom renderer API 暴露了自定义渲染 API
  • Vue3 的源码采用 monorepo 管理方式,实现了从模块管理到包管理的转变

TDD 测试驱动开发

Test-Driven Development

TDD 是一个开发测试代码和业务代码的工作流程,基于这个流程你可以写出具有极高测试覆盖率(通常接近90%)的代码。TDD还可以减少测试中发现比较难以定位的 BUG 的可能性。

TDD 的一般过程是:

  • 写一个测试运行这个测试
  • 看到预期的失败编写尽可能少的业务代码
  • 让测试通过重构代码不断重复以上过程

TDD 是单元测试的一种方式,还有一种是 BDD -- Behavior-Driven Development

本文阅读时间大约为10分钟,请听笔者娓娓道来。

Vue3 项目说明

monorepo

monorepo 是管理代码的一种方式,它是指在一个项目仓库(repo)下管理多个包,即一个仓库中维护多个包。

  • 优点:便于版本管理、依赖管理和模块间的引用
  • 缺点:仓库体积会变大

目录

  • compiler-core:与平台无关的编译器核心
  • compiler-dom: 针对浏览器的编译模块
  • compiler-sfc: 针对单文件解析
  • compiler-ssr: 针对服务端渲染的编译模块
  • reactivity:响应式系统,核心
  • runtime-core:与平台无关的运行时核心
  • runtime-dom: 针对浏览器的运行时。包括DOM API,属性,事件处理等
  • runtime-test:用于测试
  • server-renderer:用于服务器端渲染
  • size-check:用来测试代码体积
  • shared:多个包之间共享的内容
  • template-explorer:用于调试编译器输出的开发工具
  • vue:完整版本,包括运行时和编译器

想要阅读源码,可以先从 reactivity 开始,每个功能都有相应的 单测

TDD 项目准备

建议先去 Jest 官网了解以下 单测 的一些基本语法 jestjs.io/zh-Hans/doc…

  • 安装 vscode 插件:Jest、Jest Runner 和 Jest Snippets
    • 安装完后,在 xxx.test.js 文件中在每个 单测 之前就能看到 run 的标识
    • 点击便能运行此单测
  • yarn init -y
    • 初始一个 package.json
  • yarn add --dev jest
    • 安装 jest
    • 要加上 --dev,只有开发环境才会使用
  • 编写测试文件
  • 安装 ts 配置文件 解决 jest 代码块报错问题
    • npx tsc --init
    • 修改 json 文件
      "lib": ["DOM","ES6"],                                   /* Specify library files to be included in the compilation. */
      "noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
      
    • 安装相应的包
      yarn add typescript --dev
      yarn add @types/jest --dev
      
// hello.js
module.exports = () => 'Hello world'

// hello.test.js
let hello = require('hello.js')

test('should get "Hello world"', () => {
    expect(hello()).toBe('Hello world') // 测试成功
    // expect(hello()).toBe('Hello') // 测试失败
})

注意:jest 是运行在 node 环境,支持的 commonJs,所以在 js 中要用 module.exports,并且是需要用 require 导入;

使用 EMS 配置方法

  • babel 转译
    • 安装
      • yarn add --dev babel-jest @babel/core @babel/preset-env
    // babel.config.js
    module.exports = {
      presets: [
        ['@babel/preset-env', { targets: { node: 'current' } }],
        '@babel/preset-typescript'
      ]
    };
    // 编译成 nodejs 环境下的代码
    
  • node 14版本后本身,加添相应字段便可支持
    // package.json
    {
      "type": "module",
      "scripts": {
         "test": "NODE_OPTIONS=--experimental-vm-modules jest"
       }
    }
    

如果报错不能识别 NODE_OPTIONS,那么还需要安装 npm i cross-env,且修改 "test": "cross-env NODE_OPTIONS= "

// sum.js
export function add(a, b) {
    return a + b;
}

// sun.test.js
import { add } from './add';

test('adds 1 + 2 to equal 3', () => {
    expect(add(1, 2)).toBe(3);
});

写在后面

本项目是参照 mini-vue 作者的项目 + 自己阅读 vue-next 的一些思考,重敲 mini-vue 的过程中,整理形成文档。

项目地址