47-mini-vue 升级monorepo管理项目

升级 monorepo 架构

monorepo 是什么

  • 定义:单个仓库,组织代码的一种方式
  • 把所有相关的项目都放到一个仓库中, 一般情况下放到 packages 中,但不代表只能放在 packages 中
  • 本质是把相同的逻辑抽离出去进行复用

优点

  1. 共用基础设施,不用重新配置
  2. 有依赖的项目之间,调试开发十分方便
  3. 第三方的版本管理更简单

缺点

  1. 项目粒度的权限管理问题
  2. 代码量比较庞大,对新手不太友好

主流的 monorepo 工具

  1. npm
  2. yarn
  3. pnpm
  4. larne
  5. turborepo 让我们更快的执行命令 build,采用并串行,是会影响执行命令的速度的
  6. nx
  7. RushJS
    1-3 支持简单的 monorepo,复杂的就不够用了

Vue3 是如何做的

  1. vue3 从原来的 yarn 管理工具,换成了 pnpm,

    配置 workspace, 在 packages 里面放入模块,每个模块都有相应的 package.json,整体有一个 build.js 可以对所有模块进行打包

  2. pnpm 节约磁盘空间并提升安装速度

    创建非扁平化的 node_modules 文件夹

  3. build 命令 script/ build.js

  4. test 命令 依赖 build

关于 mini-vue 的 monorepo 的修改

使用 pnpm 的 monorepo
  1. workspace
  • pnpm.io/zh/workspaces
  • 命令
    • pnpm i xxx -W 安装到 root 目录下
    • pnpm i xxx -F xxx 安装到指定目录下 (指明 Pnpm的命令生效于哪个子包)
  • pnpm-workspace.yaml 配置,用来指定 packages 路径
js 复制代码
packages:
    -"packages/*"
  1. 包的依赖顺序
  • reactivity 依赖 shared
  • runtime-core 依赖 reactivity shared
  • runtime-dom 依赖 runtime-core
  • compiler-core 依赖 shared
调整 build 逻辑
使用 vitest 替换 jest
  1. vitest 是未来趋势,也是 vue 系列的一款工具
开始实操
  1. 创建 workspace 配置
  • 创建 pnpm-workspace.yaml 文件
js 复制代码
  packages:
      -"packages/*"
  1. 在对应的模块里面引入对应依赖的模块
  • 我们在根目录创建 packages 目录

    • 防止路径发生改变,我们直接将 src 里面的文件目录复制到 packages 里面
    • 参照 vue3 目录,我们把原来使用 jest 测试的目录 tests 改为 tests
    • 我们为每个模块都要创建 package.json
      • pnpm init (pnpm 10.24.0 node 22.21.1)
      • 在每个模块的 package.json 中 name 属性值改为 @guide-mini-vue/compiler-core (具体的模块名称)
        • 注意在 vue 文件目录中的 package.json 的 name 的属性值是 guide-mini-vue
  • 我们在文件内部引入文件位置做修改

    js 复制代码
    // reactivity/src/baseHandlers.ts
    import { extend, isObject } from "../shared"
    // 上面的引入路径如何修改
    import { extend, isObject } from "@guide-mini-vue/shared"
    • @guide-mini-vue/shared 这个是让本地包以第三方包的形式导入进来,我们进行处理,有两种方式:
      • 第一种:

        • v8 及以前的 pnpm 版本
          • 第一种 通过 cd 命令,进入 reactivity 目录 pnpm i @guide-mini-vue/shared
          • 第二种 进入项目根目录 pnpm i @guide-mini-vue/shared -F @guide-mimi-vue/reactivity
        • v9 及以后的 pnpm 版本
          • 尝试上面两种方法,发现在下载时直接从 官网下载包去了,而不是从本地下载,从而下载失败, 应该是版本不一样的问题,解决一下

            • 在 reactivity 目录的 package.json 中,直接手动写入 shared 包的来源, 然后通过 pnpm install 来下载,发现可以
            json 复制代码
            "dependencies": {
              "@guide-mini-vue/shared": "workspace:^1.0.0"
            }
      • 第二种:

        • 或者这个命令也可以下载本地依赖

          js 复制代码
          pnpm add @guide-mini-vue/shared --filter @guide-mini-vue/reactivity --workspace
        • 除此之外,我们发现,包的路径还有 ts 的报红,我们进行配置

        json 复制代码
        "compilerOptions": { 
          "paths": {
            "@guide-mini-vue/*": [
              "./packages/*/src"
            ]
          }
        }
    • 如果我们删除已经存在的模块可以使用这样的命令, 这里不用加 --workspace
    js 复制代码
    pnpm remove @guide-mini-vue/shared --filter @guide-mini-vue/reactivity  
    • 这里的原包与后来下载引入的包之间是软连接,修改其中一方,另一方也会发生变化
    • 参照上面的改动方法,我们把这些模块之间的引入路径都使用 @guide-mini-vue/模块名 的方式进行替换
  1. 优化点
  • ts 默认检测目录下所有 ts 后缀文件,我们进行配置,仅检测指定文件
json 复制代码
// "rootDir": "./src", // 注意这里的 rootDir 如何原来配置了路径,这里可以直接注释
"compilerOptions": {},
"include": ["packages/*/src", "packages/*/__tests__"]
  1. 总结
  • 我们根据目录知道 runtime-dom 依赖 runtime-core , runtime-core 依赖 reactivity ,runtime-dom 不能直接依赖 reactivity
  • compiler-core 不依赖其他,仅依赖一个工具库,
  • reactivity 为什么可以移动到别的框架里面去使用呢?可以和 Vue 解耦呢?因为它是高层次模块,不依赖于任何低层次的模块,runtime-core runtime-dom 都是和运行时强绑定的,reactivity 可以非常轻松的拿出去给其他模块去使用,同样的 我们在解析 template 为 render 函数时,运行时要用到 compiler-core 的代码,都是先由 compiler-core 导出到 vue 目录,再引入到运行时目录
  1. 编译流程
  • 配置 rollup.config.js
js 复制代码
// guide-mini-vue/rollup.config.js
import typescript from '@rollup/plugin-typescript'
import pkg from './package.json'
with {
    type: 'json'
};
export default {
    input: './packages/vue/src/index.ts', // ✅
    output: [{
            file: './packages/vue/dist/guide-mini-vue.cjs.js', // ✅
            format: 'cjs',
            sourcemap: true,
        },
        {
            file: './packages/vue/dist/guide-mini-vue.esm.js', // ✅
            format: 'es',
            sourcemap: true,
        },
    ],
    plugins: [
        typescript(),
    ]
}
  • 我们运行 pnpm build 进行编译,发现有一些 tests 的目录下面的文件路径会报错,我们对路径进行修改,主要是给路径增加了 /src,我们观察发现,在 packages/vue/dist 里面,经过打包出现了构建好的 js 文件。
  1. 验证我们打包的 js 文件是否有问题,我们把 example 里面的文件复制到 vue 文件夹下查看效果, 我们将 vue 中的 example 里面的文件的路径改为 dist 发现正常运行
  2. 下面我们把 jest 换为 vitest
  • pnpm i vitest -D -w 或者使用 pnpm add vitest -D --workspace-root
  • 使用 vitest 时,需要把 descibe, it, expect 从 vitest 中进行导入
    • 也可以使用 vitest.config.js 导入
js 复制代码
// vitest.config.js
import {
    defineConfig
} from 'vitest/config'
export default defineConfig({
    test: { // 一些全局 api 自动引入,我们不用进行手动引入
        globals: true
    }
})

// 使用到 jest api 的文件,我们要引入 vi 进行替换
import { vi } from 'vitest' 
// 使用 jest 的位置直接使用 vi 就可以
const onStop = vi.fn()
const runner = effect(()=>{
  dummy = foo.num
},{ onStop }) 

// package.json
"scripts": {
  "test": "vitest",
}
  • 我们运行 pnpm build ,一些测试已经通过了,一些测试报错了,我们来进行解决
    *
    1. vitest 不认识 @guide-mini-vue/shared 等模块,我们进行配置
js 复制代码
import path from 'path'
import {
    defineConfig
} from 'vitest/config'
export default defineConfig({
    test: {
        globals: true
    },
    resolve: {
        alias: [{
            find: /@guide-mini-vue\/(\w*)/,
            replacement: path.resolve(__dirname, "packages") + "/$1/src" // $1 替换为 (\w*) 里面的内容
        }]
    }
})
  1. 终端命令去掉已存在包
js 复制代码
pnpm rm -D jest @types/jest babel-jest
相关推荐
浮桥1 小时前
uniapp + h5 -- 简易抽奖转盘组件(文字版)
前端·javascript·uni-app
Swift社区1 小时前
Flutter 中如何优雅地处理复杂表单
前端·flutter·前端框架
这是个栗子1 小时前
前端开发中的常用工具函数(三)
前端·javascript·charat
慧一居士1 小时前
Vite 常用插件详解与使用指南
前端
切糕师学AI1 小时前
JavaScript 中 == 和 === 的区别
javascript·js语法
之歆1 小时前
Vue3 + Vite2.0 全栈开发实践:从零到一构建通用后台管理系统-下
javascript·vue.js·vue3
zhougl9961 小时前
前端UI框架
前端·ui
love530love10 小时前
Scoop 完整迁移指南:从 C 盘到 D 盘的无缝切换
java·服务器·前端·人工智能·windows·scoop
i220818 Faiz Ul11 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计