在接下来一段时间里,我会努力学习 Vue3 源码,并将学习过程制作成文章,与大家一起手把手从 0 开始搭建 Vue3 框架,感兴趣或喜欢的朋友不妨点个赞或订阅一下我的频道,这将会是我更新的最大动力~
本文涉及技术名词
- Monorepo 一个管理项目代码的方式
- pnpm 速度更快、更高效的npm
- esbuild 打包工具,适合开发时使用
- webpack 打包工具,适合打包业务代码
- roll-up 打包工具,适合打包框架源码等(Vite也是基于roll-up)
- minimist 参数解析工具
文章目录
介绍 Monorepo
Monorepo
是管理项目代码的一个方式,指在一个项目仓库 repo 中管理多个模块/包 package 。Vue3源码就是采用 monorepo 方式进行管理,将模块拆分到package目录中。
Monorepo 和其他结构的区别
Monorepo
与普通的模块分组不同,普通的项目结构或分组参考 Monolith 或 Multi-repo看下图
如果要一个形象的比喻,可以这样来说:
Monorepo
就像玩积木一样由多个模块搭建起来,里面的每个功能模块都有标准的接口,即使从项目中抽离出去,也能独立使用
而 Monolith
就是一块铁板,无法将模块抽离,或者只有场景完全相同的情况下才适用
Monrepo 的优缺点
优点:
- 代码复用非常简单
高复用的代码,只需专门放在一个文件夹下,其他地方引用这个文件夹即可。通常我们命名为shared
,具体如下图

正文 - 搭建 Monorepo 环境
ok,关于 monorepo
上面铺垫完了,下面开始冻手搭建环境!
Vue3中使用
pnpm
workspace
来实现monorepo
(pnpm是快速、节省磁盘空间的包管理器。主要采用符号链接的方式管理模块)
第一步 - 全局安装 pnpm
win + R打开命令小黑窗,输入下面命令全局安装 pnpm
npm install pnpm -g # 全局安装pnpm
安装完成后,找个位置建空文件夹,作为本次 Vue3源码学习全程的文件夹
,在后续我会坚持把Vue3全套底层源码更新完,敬请期待~
第二步 - 项目初始化
用vscode打开空文件夹,并在终端里输入命令。此时目录中应有一个package.json
pnpm init -y # 初始化配置文件
第2.1步
,为了使 pnpm 与npm 装包的行为一致,建立文件.npmrc
,并在文件中写下
shamefully-hoist = true
第2.2步
,下载vue3,在终端输入命令
pnpm install vue
第三步 - 配置工作目录 workspace
第3.1步
, 我们希望把所有的包都放在 packages
文件夹下进行管理(还未创建),
因此在目录下新建 pnpm-workspace.yaml 文件,并创建一个文件夹 packages
第3.2步
,在 packages 文件夹下,创建两个文件夹分别为 reactivity,shared
,并各自创建一个文件夹 src
,最后各自创建一个 index.ts
。有点绕对吧?看图一下明了。
第3.3步
,现在 packages 下有了两个包,以后的包也放在这里,想找什么都在 packages 里找。那怎样告诉pnpm这件事呢?
打开一开始创建的 pnpm-workspace.yaml 文件,写下这段代码
# 规定包都在哪个目录下管理
packages:
- "packages/*"
第四步 - 构建项目(为日后写Vue3源码做准备)
4.1 安装依赖
第4.1步
,构建项目首先要安装依赖,这里确定一下需要什么依赖:esbuild、typescript、minimist
,然后在终端里输入命令
pnpm install typescript minimist -D -w
4.2 初始化TS
第4.2步
,使用 typescript 需要进行初始化配置,在终端输入下面命令
pnpm tsc --init
此时会生成文件 tsconfig.json,在文件中复制黏贴一下JSON
{
"compilerOptions": {
"outDir": "dist", // 输出的目录
"sourceMap": true, // 采用sourcemap
"target": "es2016", // 目标语法
"module": "esnext", // 模块格式
"moduleResolution": "node", // 模块解析方式
"strict": false, // 严格模式
"resolveJsonModule": true, // 解析json模块
"esModuleInterop": true, // 允许通过es6语法引入commonjs模块
"jsx": "preserve", // jsx 不转义
"lib": ["esnext", "dom"], // 支持的类库 esnext及dom
}
}
4.3 创建模块
第4.3步
,进入 packages/reactivity
目录下,进行初始化。在终端输入以下命令
# cd packages
# cd reactivity
# pnpm init
此时目录下会生成 package.json
。复制下文json进去
{
"name": "@vue/reactivity",
"version": "1.0.0",
"main": "index.js",
"module":"dist/reactivity.esm-bundler.js",
"unpkg": "dist/reactivity.global.js",
"buildOptions": {
"name": "VueReactivity",
"formats": [
"esm-bundler",
"cjs",
"global"
]
}
}
同理,在 shared 文件夹中也是如此。然后在shared/package.json
中黏贴下文json进去
{
"name": "@vue/shared",
"version": "1.0.0",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
"buildOptions": {
"formats": [
"esm-bundler",
"cjs"
]
}
}
formats为自定义的打包格式,有
esm-bundler
在构建工具中使用的格式、esm-browser
在浏览器中使用的格式、cjs
在node中使用的格式、global
立即执行函数的格式
4.4 编译打包
打开最外层 package.json 配置,修改如图
创建scripts
文件夹,里面创建文件 dev.js
并在里面输入代码
const args = require('minimist')(process.argv.slice(2))
console.log(args);
新建终端,跑项目看看能否运行
pnpm run dev
终端打印效果如图
第五步 - reactivity 包引用 shared 包
首先配置 ts 引用关系,方便找包。打开 tsconfig.json
添加两项
"baseUrl": ".", // 表示找文件都在当前根路径下来找
"paths": {
"@vue/*":["packages/*/src"] //意味着找 "@vue/*" 的文件,都会去 packages 下寻找文件
}
在终端 cd 进入 reactivity,输入命令
pnpm install @vue/shared@workspace --filter @vue/reactivity
解释:
## install @vue/shared@workspace 从工作目录下安装这个包
## 到哪里去呢? --filter @vue/reactivity 到这里去