【学习笔记】Vue3源码解析:第一部分-实现vue3环境搭建

课程地址:【已完结】全网最详细Vue3源码解析!(一行行带你手写Vue3源码)

第一部分:实现vue3环境搭建(对应课程的第1-3节)

VUE2与VUE3的对比:

也即vue2的痛点:

  1. 对TypeScript支持不友好,所有属性都放在this对象上,难以推导数据类型
  2. 大量API挂载在vue对象原型上,难以实现TreeShaking
  3. 架构层面对跨平台DOM渲染开发支持不友好(这一点我不太理解)
  4. 推出CompositionAPI(受reactHook启发)
  5. 对虚拟DOM进行了重写,对模板的编译进行了优化

Monorepo介绍

Monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,是一种将多个peckage放在一个repo中的代码管理模式。其有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。更多可参阅:带你了解更全面的 Monorepo - 优劣、踩坑、选型
vue3中使用 yarn workspace+lerna 来管理项目。

Monorepo环境搭建

1、项目初始化:由于Monorepo是不支持npm的,所以使用yarn来初始化一个项目:

yarn init -y

2、 Monorope分包:打开项目根目录中的package.json文件,在其中加入如下配置:private与workspaces

//package.json
{"private": true,"workspaces": ["packages/*"],"name": "vue3","version": "1.0.0","main": "index.js","license": "MIT","dependencies": {"typescript": "^5.3.3"},"devDependencies": {"@rollup/plugin-json": "^6.1.0","@rollup/plugin-node-resolve": "^15.2.3","execa": "^8.0.1","rollup": "^4.9.6","rollup-plugin-typescript2": "^0.36.0"},"type":"module"
}
  • private:表示私有
  • workspaces:表示分包,所有的包都会放在packages目录下

3、新建两个包文件夹
根目录下新建packages文件夹,在packages目录下新建reactivity与shared文件夹,并分别进入reactivity与shared文件夹中,分别执行 yarn init -y 生成各自的package.json文件,并在这两个文件夹下各自创建src文件,在src中创建入口文件index.ts;
在两个index.ts文件中随意编写一点不同的代码(如不写代码,稍后打包时会报错),如:

let a = 1
export {a
}

在这里插入图片描述
4、安装ts:注意:如果是所有包都要用的,比如ts,那就安装在最外层的package.json中,即项目根目录中的package.json中:

yarn add typescript -D -W

-D表示开发环境;由于进行了分包,所以在根目录中安装需要加上 -W 配置项
在这里插入图片描述
5、通过ts的tsc命令自动生成配置项tsconfig.json:

npx tsc --init

在这里插入图片描述
6、安装rollup打包的相关依赖,在命令行中执行如下命令:

yarn add rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D -W

7、创建一个脚本执行命令scripts,在根目录中的package.json中:
在这里插入图片描述
8、配置打包选项,分别在reactivity和shared文件夹下的package.json文件中配置各个包对应的打包配置:
在这里插入图片描述
将name分别修改为"@vue/reactivity" 与 “@vue/shared”;
reactivity文件夹下的package.json增加如下配置:
shared文件夹下的package.json增加的配置中去掉global:

"buildOptions":{"name":"VueReactivity",    // shared文件夹下为"VueShared""formats":["esm-bundler","cjs","global"     // shared文件夹下的package.json增的配置中去掉此行]}

9、编写打包配置文件build.js:
在这里插入图片描述

// build.js
/ 1、获取打包目录
// const fs = require("fs")
// const execa = require("execa")import fs from "fs"
import {execa} from "execa"// 读取packages下所有文件名字,并过滤掉非文件夹,只保留packages下的文件夹
const dirs = fs.readdirSync("packages").filter(p=>{if(!fs.statSync(`packages/${p}`).isDirectory()){return false}return true
})console.log('888888',dirs)    //[ 'reactivity', 'shared' ]// 2、进行打包 并行打包
async function build(target){console.log(target,666)// await execa('rollup',['-c --bundleConfigAsCjs',"--environment",`TARGET:${target}`],{stdio:'inherit'})await execa('rollup',['-c',"--environment",`TARGET:${target}`],{stdio:'inherit'})
}function runParaller(dirs,itemfn){let result = []for(let item of dirs){result.push(itemfn(item))}return Promise.all(result)
}runParaller(dirs,build).then(()=>{console.log("成功")
})

10、根目录下新建rollup配置文件,rollup.config.js,在其中编写配置代码:

// 编写打包配置
// import ts from 'rollup-plugin-typescript2'   //解析ts
// import json from '@rollup/plugin-json'
// import resolvePlugin from '@rollup/plugin-node-resolve'  // 解析第三方插件
// import path from 'path'  // 处理路径const ts = require('rollup-plugin-typescript2')   //解析ts
const json = require('@rollup/plugin-json')
const resolvePlugin = require('@rollup/plugin-node-resolve')  // 解析第三方插件
const path = require('path')  // 处理路径// (2)获取文件路径
let packagesDir = path.resolve(__dirname,'packages')
// console.log(packagesDir, 888)    // D:\suyou\study\vue3-source-code\vue3\packages// 2.1  获取需要打包的包
let packageDir = path.resolve(packagesDir, process.env.TARGET)
// console.log(packageDir, 888)   // D:\suyou\study\vue3-source-code\vue3\packages\reactivity// 2.1  获取到每个包的项目配置
const resolve = p => path.resolve(packageDir, p)
const pkg = require(resolve('package.json'))    // 获取json
const packageOptions = pkg.buildOptions || {}
const name = path.basename(packageDir)
console.log(packageOptions, 888)   //{ name: 'VueReactivity', formats: [ 'esm-bundler', 'cjs', 'global' ] }
console.log(name, 888)   // reactivity// 3  创建一个表
const outputOptions = {"esm-bundler":{file: resolve(`dist/${name}.esm-bundler.js`),format:'es'},"cjs": {file: resolve(`dist/${name}.cjs.js`),format: 'cjs'},"global": {file: resolve(`dist/${name}.global.js`),format: 'iife'},
}const options = pkg.buildOptionsfunction createConfig(format,output){// 进行打包output.name = options.nameoutput.sourcemap = true// 生成rollup配置return {input:resolve('src/index.ts'),output,plugins:[json(),ts({  //解析tstsconfig:path.resolve(__dirname,'tsconfig.json')}),resolvePlugin()  //解析第三方插件]}
}// export default options.formats.map(format => createConfig(format, outputOptions[format]))module.exports = options.formats.map(format => createConfig(format, outputOptions[format]))

11、将 tsconfig.json中的 target 和module 字段都改为 ESNext
在这里插入图片描述
12、运行打包:npm run build,成功:
此时会发现reactivity文件夹和shared文件夹下会出现打包生成的dist文件夹:
在这里插入图片描述
13、根目录下package.json文件中新增 dev 运行脚本命令:
在这里插入图片描述
14、scripts目录下新建dev.js并在其中编写:
'-c’处增加w,表示实时监控文件更新并自动编译

// dev.js
import {execa} from "execa"// 进行打包
async function build(target){// console.log(target,666)   // reactivity  // {stdio:'inherit'} 配置项表示在子进程中输出内容可以在主包中输出await execa('rollup',['-cw','--environment',`TARGET:${target}`],{stdio:'inherit'})
}build('reactivity')

运行npm run dev,此时可以修改代码后实时打包:
在这里插入图片描述
15、解决包之间的引入问题:
在reactivity的入口文件中引入shared:

import {b} from '@vue/shared'

在这里插入图片描述
此时 @vue/shared 处会出现波浪线,提示找不到这个模块。这时就需要到tsconfig.json中增加如下配置:
在这里插入图片描述

// 解决引入的问题 ts"moduleResolution": "node",  //node"baseUrl": ".",  // 根路径"paths":{"@vue/*":["packages/*/src"]} 

总结

1、yarn init -y初始工程
2、package.json文件中,增加:
“private”:“true”;
“workspaces”:[“packages/*”]
3、项目目录下新建文件夹packages,在其中新建两个文件夹reactivity、shared,分别进入这两个文件夹,执行yarn init -y,生成各自的package.json,分别在其package.json文件中增加配置:
修改name:“@vue/reactivity” name:“@vue/shared”
增加buildOptions:{
“name”:“VueReactivity” “name”:“VueShared”
format:[
“esm-bundler”,
“cjs”,
“global”
]
}
4、分别在文件夹reactivity、shared中新建src文件夹,并在其中新建index.ts入口文件
5、使用ts就要安装ts,因为ts是全局使用的,所以需要安装在根目录下,即在根目录下执行 yarn add typescript -D -W (-D表示开发环境,由于进行了分包,所以在根目录中安装需要加上 -W 配置项)
6、ts安装完成后,node_modules目录下会新增typescript-bin-tsc,此时使用tsc生成ts配置文件:执行:npx tsc --init,自动生成 tsconfig.json 文件
7、安装rollup打包的相关依赖:
yarn add rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D -W
8、配置脚本执行命令:根目录 package.json 文件中,新增:
“scripts”:{
“build”:“node scripts/build.js”
}
9、根目录下新建scripts目录,并在其中创建build.js文件,在其中编写打包逻辑代码(详见代码)
10、根目录下新建rollup配置文件,rollup.config.js,在其中编写配置代码(详见代码)
11、将 tsconfig.json中的 target 和 module 字段都改为 ESNext(不然运行打包会报错)
12、配置开发环境打包:根目录package.json中添加dev运行命令,并在scripts目录下新建对应的dev.js文件,在其中编写打包逻辑代码(详见代码)
13、解决包之间引入问题,在tsconfig.json中增加相应配置(详见代码)
14、运行打包 npm run build 或 npm run dev,实现都可以成功打包

实践问题

编写build.js这一步跟着课程里的代码自己实践中,我遇到了问题,记录如下:

在这里插入图片描述

猜测报错信息大致是说execa不支持用require方式引入,改成import试试吧,又出现如下报错:

在这里插入图片描述

按照提示在package.json中增加"type": “module”,还是报错:

在这里插入图片描述

报错信息说execa没提供default暴露的接口,那就用 import {} 方式试试:

在这里插入图片描述

这是注意报错,不是execa引入有问题了,而是fs有问题了,因为我们配置了"type": “module”,所以把fs引入方式也改成import方式:

在这里插入图片描述

此时的报错信息为找不到rollup配置文件了。
在rollup.config.js配置文件中编写如下代码运行后报错如下:

在这里插入图片描述

按照错误提示把rollup.config.js文件后缀分别改为.cjs和.mjs,以及在execa()执行配置项中增加–bundleConfigAsCjs ,都无效;

在这里插入图片描述

在execa()执行配置项中增加–bundleConfigAsCjs 时报这个错:

在这里插入图片描述

最终解决方案如下:将依赖的引入方式都改为require形式,同时将配置文件后缀改为.cjs:

在这里插入图片描述

解决思路来源于rollup官网中的一句话。看来还是要多看官方文档。

在这里插入图片描述

rollup.config.js文件中的配置编写完成后,运行报错如下:

在这里插入图片描述

将export default 方式改为 module.exports 方式后此报错解决,出现如下报错:

在这里插入图片描述

参考 第11 步解决:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/656307.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序遮罩层滚动穿透的问题

常见的布局 外层一个遮罩层 里面一层是弹窗以及内容 这里还是个textarea 滚动到底的时候 底部的遮罩层也跟着滚动了 发生滚动穿透 处理方法是添加 <page-meta page-style"{{ showPolish ? overflow: hidden; : }}" /> page-meta必须在第一个节点

sv program module

为了避免races&#xff0c;在验证中引入program&#xff1b; Similarities between program and module block A program block can instantiate another program block in the way how the module is instantiated another module block.Both can have no or more inputs, …

【竞技宝jjb.lol】LOL:经典大龙毁一生 WE鏖战三局力克FPX

北京时间2024年1月30日&#xff0c;英雄联盟LPL2024春季赛在昨天迎来第二周首个比赛日&#xff0c;本日首场比赛由WE对阵FPX。本场比赛双方前两局战至1-1平&#xff0c;决胜局FPX一度建立不小的经济优势&#xff0c;然而太过冒险的打大龙决策最终让其功亏一篑&#xff0c;WE鏖战…

快速入门存内计算—助力人工智能加速深度学习模型的训练和推理

存内计算&#xff1a;提高计算性能和能效的新技术 传统的计算机架构是将数据存储在存储器中&#xff0c;然后将数据传输到计算单元进行处理。这种架构存在一个性能瓶颈&#xff0c;即数据传输延迟。存内计算通过将计算单元集成到存储器中&#xff0c;消除了数据传输延迟&#…

element -table,多行或列合并

需求:后端返回的表格数据,如果某列值一样,前端表格样式需要合并他们,需要合并的列的行数未知(所以需要有数据后遍历后端数据对需要合并的属性进行计数)即动态遍历表格合并 效果 - 重点方法;table自带的:span-method="objectSpanMethod"方法 代码环境:vue2 ,…

顺序表的奥秘:高效数据存储与检索

&#x1f37f;顺序表 &#x1f9c0;1、顺序表的实现&#x1f365;1.1 创建顺序表类&#x1f365;1.2 插入操作&#x1f365;1.3 查找操作&#x1f365;1.4 删除操作&#x1f365;1.5 清空操作 &#x1f9c0;2、ArrayList的说明&#x1f9c0;3、ArrayList使用&#x1f365;3.1 A…

app广告变现|如何提升app广告点击率?

提升app内的广告点击率&#xff08;CTR&#xff09;可以增加广告收入&#xff0c;而对广告主来说&#xff0c;广告点击率下降会直接影响广告主的投资回报率&#xff0c;因此&#xff0c;如何提升广告点击率&#xff0c;对app运营来说是一项重要的工作。 AdSet官网 | 聚合SDK广…

分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别

分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别 目录 分类预测 | Matlab实现SCN-Adaboost随机配置网络模型SCN的Adaboost数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SCN-Adaboost随机配置网…

C++ ffmpeg RTSP 视频推流实现, arm linux平台

环境&#xff1a; FFmpeg版本&#xff1a;n4.2.2 下载地址&#xff08;下载编译后请确认版本正确&#xff09;&#xff1a; https://ffmpeg.org//download.html 下面地址经过第三方git加速可能存在实效性&#xff1a; https://hub.fgit.cf/FFmpeg/FFmpeg/tree/n4.4.2实现代码…

【HarmonyOS应用开发】UIAbility实践第一部分(五)

一、UIAbility概述 1、UIAbility是一种包含用户界面的应用组件&#xff0c;主要用于和用户进行交互。UIAbility也是系统调度的单元&#xff0c;为应用提供窗口在其中绘制界面。 2、每一个UIAbility实例&#xff0c;都对应于一个最近任务列表中的任务。 3、一个应用可以有一个UI…

信息安全考证攻略

&#x1f525;在信息安全领域&#xff0c;拥有相关的证书不仅能提升自己的专业技能&#xff0c;更能为职业生涯增添不少光彩。下面为大家盘点了一些国内外实用的信息安全证书&#xff0c;让你一睹为快&#xff01; &#x1f31f;国内证书&#xff08;认证机构&#xff1a;中国信…

数据与资源可视化——长安链运维监控实践

前言 “链上的交易总量是多少”&#xff0c;“我的链上现在有多少区块了”&#xff0c;“节点是否存活无法第一时间感知到”&#xff0c;除sdk查询链上的相关信息外&#xff0c;今天我们介绍一种新的方式实现链上数据与相关资源的可视化的监控。 简介 监控链上数据以及链上节…

蓝桥杯-常用STL(一)

常用STL &#x1f388;1.动态数组&#x1f388;2.vector的基础使用&#x1f52d;2.1引入库&#x1f52d;2.2构造一个动态数组&#x1f52d;2.3插入元素&#x1f52d;2.4获取长度并且访问元素&#x1f52d;2.5修改元素&#x1f52d;2.6删除元素&#x1f52d;2.7清空 &#x1f38…

上个厕所的时间了解链路追踪基本概念

大家好&#xff0c;我是蓝胖子&#xff0c;随着微服务的普及&#xff0c;在面对日益复杂的架构和请求链路时&#xff0c;链路追踪技术就显得更加重要&#xff0c;今天我们花5分钟的时间&#xff0c;来掌握和链路追踪相关的基本概念。不会涉及到具体的技术框架和落地&#xff0c…

07.领域驱动设计:3种常见微服务架构模型的对比和分析

目录 1、概述 2、整洁架构 3、六边形架构 4、三种微服务架构模型的对比和分析 5、从三种架构模型看中台和微服务设计 5.1 中台建设要聚焦领域模型 5.2 微服务要有合理的架构分层 5.2.1 项目级微服务 5.2.2 企业级中台微服务 5.3 应用和资源的解耦与适配 6、总结 1、概…

AttributeError: ‘Plotter‘ object has no attribute ‘topicture‘

在以下网址找到自己的pytorch和cuda版本然后点击进入&#xff1a; https://nvidia-kaolin.s3.us-east-2.amazonaws.com/index.html 下载自己系统和python对应的最新版本 使用pip安装 pip install kaolin-0.14.0-cp38-cp38-linux_x86_64.whl

数据可视化 pycharts实现地理数据可视化(全球地图)

自用版 紧急整理一点可能要用的可视化代码&#xff0c;略粗糙 以后有机会再改 requirements&#xff1a; python3.6及以上pycharts1.9 数据格式为&#xff1a; 运行结果为&#xff1a; import pandas as pd from pyecharts.charts import Map, Timeline from pyecharts im…

【C/C++ 06】基数排序

基数排序是桶排序的一种&#xff0c;算法思路为&#xff1a; 利用队列进行数据收发创建一个队列数组&#xff0c;数组大小为10&#xff0c;每个元素都是一个队列&#xff0c;存储取模为1~9的数从低位到高位进行数据收发&#xff0c;完成排序适用于数据位不高的情况&#xff08…

C# IP v4转地址·地名 高德

需求: IPv4地址转地址 如&#xff1a;输入14.197.150.014&#xff0c;输出河北省石家庄市 SDK: 目前使用SDK为高德地图WebAPI 高德地图开放平台https://lbs.amap.com/ 可个人开发者使用&#xff0c;不过有配额限制。 WebAPI 免费配额调整公告https://lbs.amap.com/news/…

希尔伯特变换的在信号解调时的示例

1.希尔伯特变换的应用场景 希尔伯特变换&#xff0c;在数学上的含义是清晰的。它是一个数字移相器&#xff0c;可以把通过它的任何一个信号相移-90度。这个数学工具在信号解调时&#xff0c;会有非常有用的特性出现。可以看示例&#xff1a; 解释一下&#xff1a; 1.最上面的…