前言
为了深入理解vue3框架实现的原理,我打算抽时间学习一下vue3源码。之前一直想过要学习的,但由于项目忙、静不下心、懒等原因,慢慢也就搁置了。之前也只是简单的了解过一点vue3的核心源码,只是看了看网上的文章,也没有手写过;这一次打算只保留最核心的代码,手写实现一个极简的 mini-vue3
。
虽然自己在学习vue3源码过程中也是一直在参考网上一些优秀作者的技术文章一点一滴过来的。但我觉得学习一个新事物,只是去看、去了解是不够的!只有自己动手实现一遍,从0到1走过这个过程,且在这个过程中加入自己的思考,这样就算是看别人的文章、案例实现出来的也能学到很多东西。
学会吸取别人精华之处,在理解透彻的基础上自己去总结、复盘,慢慢也就会变成自己的知识。有时候学习也要学会站在巨人的肩膀上前行。
文章如果存在问题,欢迎大家评论区指点、讨论。如果对你有帮助,你的点赞、评论、收藏是我最大的动力。
学习交流群可评论区获取,就不贴码了掘金不让的!
谨以此篇记录自己的学习过程,同时,也希望能够帮助到其他同学。
源码工程初始化
首先找好目标文件夹,在终端执行 npm init -y
初始化一个 package.json
文件
使用 rollup 搭建 mini-vue3 源码环境
什么是 rollup
rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。
为什么是 rollup
rollup
的特点是 ES6 模块和代码 Tree-shaking
;这些功能 webpack
同样支持,除此之外 webpack
还支持热模块替换、代码分割、静态资源导入等更多功能。
当开发应用时优先选择的是 webpack
,但如果项目只需要打包出一个简单的 bundle
包,并是基于 ES6 模块开发的,那就可以考虑使用 rollup
。
rollup
相比 webpack
,它更少的功能和更简单的 api,是我们在打包类库时选择它的主要原因。
基础依赖安装
-
安装
rollup
用于我们源码的打包构建pnpm install rollup
-
安装 babel,使用babel需要安装核心模块
@babel/core
es6+语法写起来很爽,但是浏览器不兼容,想写的代码在浏览器上跑起来就需要使用 babel
babel 可以将我们写的es6+的语法转换为浏览器兼容的语法,比如将箭头函数转换为普通函数等
pnpm install @babel/core
-
rollup 与 babel 关联
pnpm install rollup-plugin-babel
-
浏览器兼容:将 ES6 语法转译为 ES5
pnpm install @babel/preset-env
-
基础依赖合并写法
pnpm install rollup @babel/core rollup-plugin-babel @babel/preset-env -D
monorepo开发环境配置
源码目录结构:
lua
|---packages
|---reactivity 响应式核心
|---src
|---...
|---index.js
|---package.json
|---shared 各模块通用方法
|---src
|---...
|---index.js
|---package.json
|---vue 我们最终vue
|---src
|---...
|---index.js 打包入口
|---package.json
根目录下 packages
目录下每个模块都要包含src、index.js、package.json
文件,且需要注意package.json
中 name
字段的名称。
例如 shared
模块 package.json
文件的 name:@mini-vue3/shared
,表示 shared
是属于 @mini-vue3
依赖下的子模块
- shared模块
js
// package.json
{
"name": "@mini-vue3/shared",
"version": "1.0.0",
"description": "",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@mini-vue3/shared": "workspace:^1.0.0"
}
}
- reactivity模块
js
// package.json
{
"name": "@mini-vue3/reactivity",
"version": "1.0.0",
"description": "",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@mini-vue3/shared": "workspace:^1.0.0"
}
}
注意: 此时在 reactivity
模块中需要使用到 shared
包时,就需要在当前目录下安装pnpm add @mini-vue3/shared
而依赖名称就是对应模块下 package.json
中 name
字段。所以这个name字段命名要注意、使用时不要搞错了。
但此时会发现安装完后,打包测试发现包与包之间互相使用时是会报错的。 别急,往下看。
添加monorepo生效的配置文件
要想 monorepo
相关配置生效,还需要在项目根目录下新建一个 pnpm-workspace.yaml
文件:
vbnet
packages:
- 'packages/*'
意思是将 packages
目录下所有的目录都作为单独的包进行管理。
通过这样一个简单的配置,monorepo
开发环境就搭建好了,此时发现包与包依赖就可以互相引用了。
创建 Rollup 配置文件
rollup
的默认配置文件:项目根目录下创建 rollup.config.js
文件
js
import babel from 'rollup-plugin-babel'
// 导出 rollup 配置对象
export default {
input: "./packages/vue/src/index.js", // 打包入口
output: { // 打包出口:可定义为数组,输出多种构件
// file: 'dist/miniVue.js', // 打包输出文件
file: './packages/vue/dist/minivue3.js', // 打包输出文件
// 打包格式(可选项):iife(立即执行函数)、esm(ES6 模块)、cjs(Node 规范)、umd(支持 amd + cjs)
format: 'umd',
//当format为iife和umd时必须提供,导出的模块名 Minivue3 将作为全局变量挂在window下
name: 'Minivue3',
// 开启 sourcemap 源码映射,打包时会生成 .map 文件;作用:浏览器调试ES5代码时,可定位到ES6源代码所在行;
sourcemap: true,
},
// 使用 Rollup 插件转译代码
plugins: [
babel({
// 忽略 node_modules 目录下所有文件(**:所有文件夹下的所有文件)
exclude: 'node_modules/**'
}),
]
}
创建 rollup 构建脚本
添加构建脚本命令,在源码根目录 package.json
中加入scripts
:
js
"scripts": {
"dev": "rollup -c -w",
"build": "rollup -c",
},
脚本具体解释:
- rollup 命令:默认会去找
node_module/bin/rollup
; - -c:config 选项,使用配置文件,默认找 rollup.config.js;
- -w:watch 选项,监听文件变化;当文件发生变化时重新打包;
打包
执行脚本命令打包:pnpm dev
可能报错如下:
package.json中加入:
js
"type": "module",
重新执行命令后,打包成功:
总结
至此,已经完成了一个基于 rollup
的 mini-vue3
源码的工程。 接下来可以开始专心去实现vue3
中的核心api
了。