1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-08-05 20:31:37 +08:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Guide
7b0d616dcb [docs update]网络部分添加Websocket的介绍 2023-12-01 12:42:42 +08:00
Guide
f19b6b151d
Merge pull request #2211 from ZeroMarker/main
文字更正
2023-11-30 17:17:46 +08:00
ZeroMarker
660b3e1424
文字更正
Java基础常见面试题总结(上)
2023-11-30 15:12:53 +08:00
Guide
94d4caa3ef [docs update]新增问题排查和性能优化开源项目 2023-11-29 23:28:10 +08:00
Guide
100e30a8f7 [docs update]分布式锁总结完善 2023-11-29 23:27:36 +08:00
Guide
5b7c40bdd6 [docs update]Redis Stream 消息队列内容完善+部分笔误完善 2023-11-29 23:27:15 +08:00
Guide
a46f5a9383
Merge pull request #2210 from Mister-Hope/deps
chore: update deps
2023-11-29 13:14:27 +08:00
Mr.Hope
5fb624b890 chore: update deps 2023-11-28 17:45:00 +08:00
15 changed files with 1668 additions and 1320 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@ format-markdown.py
package-lock.json
lintmd-config.json
pnpm-lock.yaml
pnpm-lock.yaml

View File

@ -70,9 +70,9 @@ export default hopeTheme({
mdEnhance: {
align: true,
codetabs: true,
container: true,
figure: true,
gfm: true,
hint: true,
include: {
resolvePath: (file, cwd) => {
if (file.startsWith("@"))

View File

@ -17,6 +17,34 @@ HTTP 协议基于 TCP 协议,发送 HTTP 请求之前首先要建立 TCP 连
另外, HTTP 协议是”无状态”的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。
## Websocket全双工通信协议
WebSocket 是一种基于 TCP 连接的全双工通信协议,即客户端和服务器可以同时发送和接收数据。
WebSocket 协议在 2008 年诞生2011 年成为国际标准几乎所有主流较新版本的浏览器都支持该协议。不过WebSocket 不只能在基于浏览器的应用程序中使用,很多编程语言、框架和服务器都提供了 WebSocket 支持。
WebSocket 协议本质上是应用层的协议,用于弥补 HTTP 协议在持久通信能力上的不足。客户端和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
![Websocket 示意图](https://oss.javaguide.cn/github/javaguide/system-design/web-real-time-message-push/1460000042192394.png)
下面是 WebSocket 的常见应用场景:
- 视频弹幕
- 实时消息推送,详见[Web 实时消息推送详解](https://javaguide.cn/system-design/web-real-time-message-push.html)这篇文章
- 实时游戏对战
- 多用户协同编辑
- 社交聊天
- ……
WebSocket 的工作过程可以分为以下几个步骤:
1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 `Upgrade: websocket``Sec-WebSocket-Key` 等字段,表示要求升级协议为 WebSocket
2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket它将回复一个 HTTP 101 状态码,响应头中包含 `Connection: Upgrade``Sec-WebSocket-Accept: xxx` 等字段、表示成功升级到 WebSocket 协议。
3. 客户端和服务器之间建立了一个 WebSocket 连接可以进行双向的数据传输。数据以帧frames的形式进行传送WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。
另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。
## SMTP:简单邮件传输(发送)协议
**简单邮件传输(发送)协议SMTPSimple Mail Transfer Protocol** 基于 TCP 协议,是一种用于发送电子邮件的协议

View File

@ -260,6 +260,49 @@ GET 和 POST 是 HTTP 协议中两种常用的请求方法,它们在不同的
再次提示,重点搞清两者在语义上的区别即可,实际使用过程中,也是通过语义来区分使用 GET 还是 POST。不过也有一些项目所有的请求都用 POST这个并不是固定的项目组达成共识即可。
## WebSocket
### 什么是 WebSocket?
WebSocket 是一种基于 TCP 连接的全双工通信协议,即客户端和服务器可以同时发送和接收数据。
WebSocket 协议在 2008 年诞生2011 年成为国际标准几乎所有主流较新版本的浏览器都支持该协议。不过WebSocket 不只能在基于浏览器的应用程序中使用,很多编程语言、框架和服务器都提供了 WebSocket 支持。
WebSocket 协议本质上是应用层的协议,用于弥补 HTTP 协议在持久通信能力上的不足。客户端和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
![Websocket 示意图](https://oss.javaguide.cn/github/javaguide/system-design/web-real-time-message-push/1460000042192394.png)
下面是 WebSocket 的常见应用场景:
- 视频弹幕
- 实时消息推送,详见[Web 实时消息推送详解](https://javaguide.cn/system-design/web-real-time-message-push.html)这篇文章
- 实时游戏对战
- 多用户协同编辑
- 社交聊天
- ……
### WebSocket 和 HTTP 有什么区别?
WebSocket 和 HTTP 两者都是基于 TCP 的应用层协议,都可以在网络中传输数据。
下面是二者的主要区别:
- WebSocket 是一种双向实时通信协议,而 HTTP 是一种单向通信协议。并且HTTP 协议下的通信只能由客户端发起,服务器无法主动通知客户端。
- WebSocket 使用 ws:// 或 wss://(使用 SSL/TLS 加密后的协议,类似于 HTTP 和 HTTPS 的关系) 作为协议前缀HTTP 使用 http:// 或 https:// 作为协议前缀。
- WebSocket 可以支持扩展,用户可以扩展协议,实现部分自定义的子协议,如支持压缩、加密等。
- WebSocket 通信数据格式比较轻量,用于协议控制的数据包头部相对较小,网络开销小,而 HTTP 通信每次都要携带完整的头部网络开销较大HTTP/2.0 使用二进制帧进行数据传输,还支持头部压缩,减少了网络开销)。
### WebSocket 的工作过程是什么样的?
WebSocket 的工作过程可以分为以下几个步骤:
1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 `Upgrade: websocket``Sec-WebSocket-Key` 等字段,表示要求升级协议为 WebSocket
2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket它将回复一个 HTTP 101 状态码,响应头中包含 `Connection: Upgrade``Sec-WebSocket-Accept: xxx` 等字段、表示成功升级到 WebSocket 协议。
3. 客户端和服务器之间建立了一个 WebSocket 连接可以进行双向的数据传输。数据以帧frames的形式进行传送WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。
另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。
## PING
### PING 命令的作用是什么?

View File

@ -171,12 +171,47 @@ pub/sub 既能单播又能广播,还支持 channel 的简单正则匹配。不
为此Redis 5.0 新增加的一个数据结构 `Stream` 来做消息队列。`Stream` 支持:
- 发布 / 订阅模式
- 按照消费者组进行消费
- 按照消费者组进行消费(借鉴了 Kafka 消费者组的概念)
- 消息持久化( RDB 和 AOF
- ACK 机制(通过确认机制来告知已经成功处理了消息)
- 阻塞式获取消息
`Stream` 使用起来相对要麻烦一些,这里就不演示了。而且,`Stream` 在实际使用中依然会有一些小问题不太好解决比如在 Redis 发生故障恢复后不能保证消息至少被消费一次。
`Stream` 的结构如下:
综上,和专业的消息队列相比,使用 Redis 来实现消息队列还是有很多欠缺的地方比如消息丢失和堆积问题不好解决。因此,我们通常建议不要使用 Redis 来做消息队列,你完全可以选择市面上比较成熟的一些消息队列比如 RocketMQ、Kafka。
![](https://oss.javaguide.cn/github/javaguide/database/redis/redis-stream-structure.png)
这是一个有序的消息链表,每个消息都有一个唯一的 ID 和对应的内容。ID 是一个时间戳和序列号的组合,用来保证消息的唯一性和递增性。内容是一个或多个键值对(类似 Hash 基本数据类型),用来存储消息的数据。
这里再对图中涉及到的一些概念,进行简单解释:
- `Consumer Group`:消费者组用于组织和管理多个消费者。消费者组本身不处理消息,而是再将消息分发给消费者,由消费者进行真正的消费
- `last_delivered_id`:标识消费者组当前消费位置的游标,消费者组中任意一个消费者读取了消息都会使 last_delivered_id 往前移动。
- `pending_ids`:记录已经被客户端消费但没有 ack 的消息的 ID。
下面是`Stream` 用作消息队列时常用的命令:
- `XADD`:向流中添加新的消息。
- `XREAD`:从流中读取消息。
- `XREADGROUP`:从消费组中读取消息。
- `XRANGE`:根据消息 ID 范围读取流中的消息。
- `XREVRANGE`:与 `XRANGE` 类似,但以相反顺序返回结果。
- `XDEL`:从流中删除消息。
- `XTRIM`:修剪流的长度,可以指定修建策略(`MAXLEN`/`MINID`)。
- `XLEN`:获取流的长度。
- `XGROUP CREATE`:创建消费者组。
- `XGROUP DESTROY` 删除消费者组
- `XGROUP DELCONSUMER`:从消费者组中删除一个消费者。
- `XGROUP SETID`:为消费者组设置新的最后递送消息 ID
- `XACK`:确认消费组中的消息已被处理。
- `XPENDING`:查询消费组中挂起(未确认)的消息。
- `XCLAIM`:将挂起的消息从一个消费者转移到另一个消费者。
- `XINFO`:获取流(`XINFO STREAM`)、消费组(`XINFO GROUPS`)或消费者(`XINFO CONSUMERS`)的详细信息。
`Stream` 使用起来相对要麻烦一些,这里就不演示了。
总的来说,`Stream` 已经可以满足一个消息队列的基本要求了。不过,`Stream` 在实际使用中依然会有一些小问题不太好解决比如在 Redis 发生故障恢复后不能保证消息至少被消费一次。
综上,和专业的消息队列相比,使用 Redis 来实现消息队列还是有很多欠缺的地方比如消息丢失和堆积问题不好解决。因此,我们通常建议不要使用 Redis 来做消息队列,你完全可以选择市面上比较成熟的一些消息队列比如 RocketMQ、Kafka。不过如果你就是想要用 Redis 来做消息队列的话,那我建议你优先考虑 `Stream`,这是目前相对最优的 Redis 消息队列实现。
相关阅读:[Redis 消息队列发展历程 - 阿里开发者 - 2022](https://mp.weixin.qq.com/s/gCUT5TcCQRAxYkTJfTRjJw)。

View File

@ -374,9 +374,9 @@ IdGenerator 生成的唯一 ID 组成如下:
![IdGenerator 生成的 ID 组成](https://oss.javaguide.cn/github/javaguide/system-design/distributed-system/idgenerator-distributed-id-schematic-diagram.png)
- **timestamp (位数不固定)**时间差,是生成 ID 时的系统时间减去 BaseTime(基础时间,也称基点时间、原点时间、纪元时间,默认值为 2020 年) 的总时间差(毫秒单位)。初始为 5bits随着运行时间而增加。如果觉得默认值太老你可以重新设置不过要注意这个值以后最好不变。
- **timestamp (位数不固定)**时间差,是生成 ID 时的系统时间减去 BaseTime(基础时间,也称基点时间、原点时间、纪元时间,默认值为 2020 年) 的总时间差(毫秒单位)。初始为 5bits随着运行时间而增加。如果觉得默认值太老你可以重新设置不过要注意这个值以后最好不变。
- **worker id (默认 6 bits)** 机器 id机器码最重要参数是区分不同机器或不同应用的唯一 ID最大值由 `WorkerIdBitLength`(默认 6限定。如果一台服务器部署多个独立服务需要为每个服务指定不同的 WorkerId。
- **sequence (默认 6 bits)**序列数,是每毫秒下的序列数,由参数中的 `SeqBitLength`(默认 6限定。增加 `SeqBitLength` 会让性能更高,但生成的 ID 也会更长。
- **sequence (默认 6 bits)**序列数,是每毫秒下的序列数,由参数中的 `SeqBitLength`(默认 6限定。增加 `SeqBitLength` 会让性能更高,但生成的 ID 也会更长。
Java 语言使用示例:<https://github.com/yitter/idgenerator/tree/master/Java>

View File

@ -365,6 +365,14 @@ private static class LockData
## 总结
这篇文章我们介绍了实现分布式锁的两种常见方式。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要看业务的具体需求。如果对性能要求比较高的话,建议使用 Redis 实现分布式锁。如果对可靠性要求比较高的话,建议使用 ZooKeeper 实现分布式锁。
在这篇文章中,我介绍了实现分布式锁的两种常见方式: Redis 和 ZooKeeper。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要看业务的具体需求。
- 如果对性能要求比较高的话,建议使用 Redis 实现分布式锁(优先选择 Redisson 提供的现成的分布式锁,而不是自己实现)。
- 如果对可靠性要求比较高的话,建议使用 ZooKeeper 实现分布式锁(推荐基于 Curator 框架实现)。不过,现在很多项目都不会用到 ZooKeeper如果单纯是因为分布式锁而引入 ZooKeeper 的话,那是不太可取的,不建议这样做,为了一个小小的功能增加了系统的复杂度。
最后,再分享两篇我觉得写的还不错的文章:
- [分布式锁实现原理与最佳实践 - 阿里云开发者](https://mp.weixin.qq.com/s/JzCHpIOiFVmBoAko58ZuGw)
- [聊聊分布式锁 - 字节跳动技术团队](https://mp.weixin.qq.com/s/-N4x6EkxwAYDGdJhwvmZLw)
<!-- @include: @article-footer.snippet.md -->

View File

@ -15,12 +15,7 @@ title: JavaGuideJava学习&面试指南)
<div align="center">
[![logo](https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png)](https://github.com/Snailclimb/JavaGuide)
[![阅读](https://img.shields.io/badge/阅读-read-brightgreen.svg)](https://javaguide.cn/)
![Stars](https://img.shields.io/github/stars/Snailclimb/JavaGuide)
![forks](https://img.shields.io/github/forks/Snailclimb/JavaGuide)
![issues](https://img.shields.io/github/issues/Snailclimb/JavaGuide)
![logo](https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png)
[GitHub](https://github.com/Snailclimb/JavaGuide) | [Gitee](https://gitee.com/SnailClimb/JavaGuide)

View File

@ -60,7 +60,7 @@ Java 虚拟机JVM是运行 Java 字节码的虚拟机。JVM 有针对不
#### JDK 和 JRE
JDKJava Development Kit它是功能齐全的 Java SDK是提供给开发者使用的,能够创建和编译 Java 程序。他包含了 JRE同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc文档注释工具、jdb调试器、jconsole基于 JMX 的可视化监控⼯具、javap反编译工具等等。
JDKJava Development Kit它是功能齐全的 Java SDK是提供给开发者使用,能够创建和编译 Java 程序的开发套件。它包含了 JRE同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc文档注释工具、jdb调试器、jconsole基于 JMX 的可视化监控⼯具、javap反编译工具等等。
JREJava Runtime Environment 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,主要包括 Java 虚拟机JVM、Java 基础类库Class Library

View File

@ -72,7 +72,7 @@ String message = STR."Greetings \{name}!";
- STR 是模板处理器。
- `\{name}`为表达式,运行时,这些表达式将被相应的变量值替换。
Java 目前支持三种模板处理器:
Java 目前支持三种模板处理器:
- STR自动执行字符串插值即将模板中的每个嵌入式表达式替换为其值转换为字符串
- FMT和 STR 类似,但是它还可以接受格式说明符,这些格式说明符出现在嵌入式表达式的左边,用来控制输出的样式

View File

@ -18,7 +18,7 @@ category: 开源项目
另外,我的公众号还会定期分享优质开源项目,每月一期,每一期我都会精选 5 个高质量的 Java 开源项目。
目前已经更新到了第 22 期:
目前已经更新到了第 24 期:
1. [一款基于 Spring Boot + Vue 的一站式开源持续测试平台](http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247515383&idx=1&sn=ba7244020c05d966b483d8c302d54e85&chksm=cea1f33cf9d67a2a111bcf6cadc3cc1c44828ba2302cd3e13bbd88349e43d4254808e6434133&scene=21#wechat_redirect)。
2. [用 Java 写个沙盒塔防游戏!已上架 Steam,Apple Store](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247515981&idx=1&sn=e4b9c06af65f739bdcdf76bdc35d59f6&chksm=cea1f086f9d679908bd6604b1c42d67580160d9789951f3707ad2f5de4d97aa72121d8fe777e&token=435278690&lang=zh_CN&scene=21#wechat_redirect)
@ -42,6 +42,7 @@ category: 开源项目
20. [这是我见过最强大的技术社区实战项目!!](https://mp.weixin.qq.com/s/tdBQ0Td_Gsev4AaIlq5ltg)
21. [颜值吊打 Postman这款开源 API 调试工具我超爱!!](https://mp.weixin.qq.com/s/_KXBGckyS--P97G48zXCrw)
22. [轻量级 Spring够优雅](https://mp.weixin.qq.com/s/tl2539hsYsvEm8wjmQwDEg)
23. [这是我见过最强的 Java 版内网穿透神器!](https://mp.weixin.qq.com/s/4hyQsTICIUf9EvAVrC6wEg)
推荐你在我的公众号“**JavaGuide**”回复“**开源**”在线阅读[「优质开源项目推荐」](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg2OTA0Njk0OA==&action=getalbum&album_id=1345382825083895808&scene=173&from_msgid=2247516459&from_itemidx=1&count=3&nolastread=1#wechat_redirect)系列。

View File

@ -10,12 +10,18 @@ icon: codelibrary-fill
- [guava](https://github.com/google/guava "guava")Guava 是一组核心库,其中包括新的集合类型(例如 multimap 和 multiset不可变集合图形库以及用于并发、I / O、哈希、原始类型、字符串等的实用程序
- [hutool](https://github.com/looly/hutool "hutool") : Hutool 是一个 Java 工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让 Java 语言也可以“甜甜的”。
- [p3c](https://github.com/alibaba/p3c "p3c")Alibaba Java Coding Guidelines pmd implements and IDE plugin。Eclipse 和 IDEA 上都有该插件,推荐使用!
- [arthas](https://github.com/alibaba/arthas "arthas")Arthas 是 Alibaba 开源的 Java 诊断工具。
- [sonarqube](https://github.com/SonarSource/sonarqube "sonarqube")SonarQube 支持所有开发人员编写更干净,更安全的代码。
- [checkstyle](https://github.com/checkstyle/checkstyle "checkstyle") :Checkstyle 是一种开发工具,可帮助程序员编写符合编码标准的 Java 代码。它使检查 Java 代码的过程自动化,从而使人们不必执行这项无聊(但很重要)的任务。这使其成为想要实施编码标准的项目的理想选择。
- [pmd](https://github.com/pmd/pmd "pmd") : 可扩展的多语言静态代码分析器。
- [spotbugs](https://github.com/spotbugs/spotbugs "spotbugs") :SpotBugs 是 FindBugs 的继任者。静态分析工具,用于查找 Java 代码中的错误。
## 问题排查和性能优化
- [arthas](https://github.com/alibaba/arthas "arthas")Alibaba 开源的 Java 诊断工具,可以实时监控和诊断 Java 应用程序。它提供了丰富的命令和功能,用于分析应用程序的性能问题,包括启动过程中的资源消耗和加载时间。
- [Async Profiler](https://github.com/async-profiler/async-profiler):低开销的异步 Java 性能分析工具,用于收集和分析应用程序的性能数据。
- [Spring Boot Startup Report](https://github.com/maciejwalkowiak/spring-boot-startup-report):用于生成 Spring Boot 应用程序启动报告的工具。它可以提供详细的启动过程信息,包括每个 bean 的加载时间、自动配置的耗时等,帮助你分析和优化启动过程。
- [Spring Startup Analyzer](https://github.com/linyimin0812/spring-startup-analyzer/blob/main/README_ZH.md):采集 Spring 应用启动过程数据,生成交互式分析报告(HTML),用于分析 Spring 应用启动卡点,支持 Spring Bean 异步初始化,减少优化 Spring 应用启动时间。UI 参考[Spring Boot Startup Report](https://github.com/maciejwalkowiak/spring-boot-startup-report)实现。
## 文档处理
### Excel

View File

@ -302,6 +302,15 @@ Websocket 应该是大家都比较熟悉的一种实现消息推送的方式,
![Websocket 示意图](https://oss.javaguide.cn/github/javaguide/system-design/web-real-time-message-push/1460000042192394.png)
WebSocket 的工作过程可以分为以下几个步骤:
1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 `Upgrade: websocket``Sec-WebSocket-Key` 等字段,表示要求升级协议为 WebSocket
2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket它将回复一个 HTTP 101 状态码,响应头中包含 `Connection: Upgrade``Sec-WebSocket-Accept: xxx` 等字段、表示成功升级到 WebSocket 协议。
3. 客户端和服务器之间建立了一个 WebSocket 连接可以进行双向的数据传输。数据以帧frames的形式进行传送而不是传统的 HTTP 请求和响应。WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。
另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。
SpringBoot 整合 Websocket先引入 Websocket 相关的工具包,和 SSE 相比额外的开发成本。
```xml

View File

@ -20,19 +20,19 @@
"markdownlint"
]
},
"packageManager": "pnpm@8.9.2",
"packageManager": "pnpm@8.11.0",
"dependencies": {
"@vuepress/client": "2.0.0-beta.67",
"@vuepress/plugin-search": "2.0.0-beta.67",
"@vuepress/utils": "2.0.0-beta.67",
"@vuepress/client": "2.0.0-rc.0",
"@vuepress/plugin-search": "2.0.0-rc.0",
"@vuepress/utils": "2.0.0-rc.0",
"husky": "8.0.3",
"markdownlint-cli": "0.37.0",
"mathjax-full": "3.2.2",
"nano-staged": "0.8.0",
"nodejs-jieba": "0.0.2",
"prettier": "3.0.3",
"vue": "3.3.7",
"vuepress": "2.0.0-beta.67",
"vuepress-theme-hope": "2.0.0-beta.241"
"prettier": "3.1.0",
"vue": "3.3.9",
"vuepress": "2.0.0-rc.0",
"vuepress-theme-hope": "2.0.0-rc.1"
}
}

2812
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff