Skip to content

Commit f54d5ff

Browse files
committed
docs: refactor and relocate version and usage notes in README
1 parent 21f18c6 commit f54d5ff

1 file changed

Lines changed: 152 additions & 149 deletions

File tree

README.md

Lines changed: 152 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -56,161 +56,12 @@
5656

5757
感谢所有支持本项目的用户和开发者,也特别感谢 Halo CMS 团队为插件生态提供的优秀平台。
5858

59-
## 版本说明
60-
61-
插件提供两个版本:
62-
63-
- **全量版**:包含所有功能,包括代码高亮等依赖 JS 的相关功能。
64-
- **轻量版**:轻量级版本,不包含 JS 相关功能和相关依赖。
65-
66-
### 轻量版的优势
67-
68-
- 更小的插件体积
69-
- 更快的启动速度
70-
- 更低的内存占用
71-
- 更低的系统性能要求
72-
- 支持全平台(全量版仅支持以下平台:Linux ARM64、Linux x86_64、macOS ARM64、macOS x86_64、Windows x86_64)
73-
74-
### 轻量版本缺少的功能
75-
76-
- 代码高亮(Shiki.js 渲染)
77-
78-
<!-- - 图表渲染(Mermaid)
79-
- 公式渲染(KaTeX) -->
80-
81-
- 其他 JS 运行时相关功能
82-
83-
如果您需要上述功能,请使用全量版。
84-
85-
## 全量版使用须知
86-
87-
⏱️ **首次使用提示**: 全量版的 JavaScript 功能(如 Shiki 代码高亮)在首次调用时需要 1~3 秒进行环境初始化。这是正常现象,之后的调用速度会非常快。
88-
89-
> ⚠️ **重要**: 全量版依赖 Javet 加载 Node.js 原生库(基于 JNI),受 Halo 插件架构限制,存在[已知问题](#全量版已知问题)
90-
91-
### 基本使用要求
92-
93-
1. **请勿热重载更新**: 请勿直接覆盖更新(如使用应用商店/插件列表的快捷更新操作)
94-
2. **正确的更新流程**:
95-
- 方法一:停止插件 → 卸载插件 → **重启 Halo** → 安装新版本 → 启动插件
96-
- 方法二:停止插件 → 卸载插件 → 安装新版本 → **重启 Halo** → 启动插件
97-
3. **卸载推荐做法**: 在卸载全量版后**重启 Halo** 确保原生库资源完全释放。
98-
99-
### 全量版已知问题
100-
101-
- 问题一:卸载后重新安装全量版插件,不重启就启用。调用 JS 相关 API 时会出现错误:
102-
- **首次安装并启动**: 正常工作
103-
- **禁用后重新启用**: 正常工作
104-
- **卸载后重新安装**: ❌ 会出现 `JavetException: Javet library is not loaded` 错误
105-
- **重启 Halo 后**: 恢复正常工作
106-
107-
#### 问题一解决方案
108-
109-
安装好新版本插件后**先别启用**
110-
在启用新版本插件之前,请**先重启 Halo CMS**
111-
112-
未来版本会将引擎作为前置依赖插件,更新本插件不再需要重启。
113-
114-
<details>
115-
<summary>📖 技术原因分析(展开查看详细说明)</summary>
116-
117-
根据错误日志和 Halo 架构分析:
118-
119-
**问题根源**:
120-
121-
1. **Halo 插件架构**: 根据 [Halo 开发文档 - 插件架构](https://docs.halo.run/developer-guide/core/framework), Halo 使用
122-
Spring Plugin Framework 实现插件隔离
123-
- 每个插件拥有独立的 Spring ApplicationContext
124-
- 每个插件使用独立的 classloader 加载资源
125-
- 插件间通过 ExtensionPoint 机制通信
126-
- classloader 完全隔离,无法跨插件共享类或资源
127-
128-
2. **Javet 原生库加载机制**:
129-
- Javet 需要从 JAR 中提取原生库文件(`.dll`/`.so`/`.dylib`)到临时目录
130-
- JVM 通过 JNI 加载这些原生库文件
131-
- 原生库文件一旦加载,会被 JVM 锁定
132-
133-
3. **冲突发生过程**:
134-
- 安装插件时,Javet 提取原生库文件到 `C:\Users\用户名\AppData\Local\Temp\javet\进程ID\`(以 Windows 举例)
135-
- JVM 加载这些文件并锁定
136-
- 卸载插件时,虽然 classloader 被销毁,但原生库文件仍被 JVM 锁定,无法删除
137-
- 重新安装时,Javet 尝试提取新文件到同一位置
138-
- 因为文件被锁定,提取失败
139-
- Javet 初始化失败,报错 `Javet library is not loaded because <null>`
140-
141-
**典型错误日志解读**:
142-
143-
```
144-
WARN - Failed to write to ...libjavet-node-windows-x86_64.v.4.1.7.dll because it is locked
145-
ERROR - Native Library already loaded in another classloader
146-
ERROR - JavetException: Javet library is not loaded because <null>
147-
```
148-
149-
这三条日志清晰地展示了整个失败过程:
150-
151-
1. 尝试写入文件失败(文件被锁定)
152-
2. 检测到库已在其他 classloader 中加载
153-
3. 初始化失败,因为无法提取必要的库文件
154-
155-
**为什么重启有效**:
156-
157-
- 重启 Halo 会终止 JVM 进程
158-
- JVM 终止时会释放所有文件锁
159-
- 临时目录中的原生库文件会被清理
160-
- 新的 Halo 进程启动后,Javet 可以正常提取和加载原生库
161-
162-
**为什么 Javet 文档中提到的 JVM 参数无效**:
163-
164-
`-Djavet.lib.loading.suppress.error=true` 这个参数的作用是:
165-
166-
- 抑制 Javet 在检测到"already loaded in another classloader"时的错误日志
167-
- **但无法解决文件锁定问题**
168-
- 当库文件无法提取时,Javet 根本无法完成初始化
169-
- 因此该参数在这个场景下无效
170-
171-
**架构层面的限制**:
172-
173-
这个问题是 JVM/JNI + 插件 classloader 隔离的固有矛盾:
174-
175-
- Halo 的插件隔离设计保证了安全性和稳定性
176-
- 但也导致原生库这类 JVM 级别资源难以管理
177-
- 类似问题在所有使用 classloader 隔离的插件系统中都存在
178-
- 这不是 Javet 或本插件的 bug,而是架构层面的限制
179-
180-
**相关技术文档**:
181-
182-
- [Javet - Load and Unload](https://www.caoccao.com/Javet/reference/resource_management/load_and_unload.html)
183-
- [Javet Issue #124 - Classloader Reload](https://github.com/caoccao/Javet/issues/124)
184-
- [Halo - Plugin Framework](https://docs.halo.run/developer-guide/core/framework)
185-
186-
</details>
187-
188-
## TODO
189-
190-
<details><summary>展开折叠内容</summary>
191-
192-
- [ ] 提供随机文章 API
193-
- [ ] 提供预计阅读时间 API,及相关配置项
194-
- [ ] 提供图表渲染 API
195-
- [ ] 提供公式渲染 API
196-
- [ ] 分离 Node.js 环境支持为可选前置插件(预计 3.0 版本实现)
197-
198-
</details>
199-
20059
## 文档目录
20160

20261
- [halo-plugin-extra-api](#halo-plugin-extra-api)
20362
- [简介](#简介)
20463
- [核心理念](#核心理念)
20564
- [功能介绍](#功能介绍)
206-
- [版本说明](#版本说明)
207-
- [轻量版的优势](#轻量版的优势)
208-
- [轻量版本缺少的功能](#轻量版本缺少的功能)
209-
- [全量版使用须知](#全量版使用须知)
210-
- [基本使用要求](#基本使用要求)
211-
- [全量版已知问题](#全量版已知问题)
212-
- [问题一解决方案](#问题一解决方案)
213-
- [TODO](#todo)
21465
- [文档目录](#文档目录)
21566
- [Finder API 文档](#finder-api-文档)
21667
- [文档类型定义](#文档类型定义)
@@ -228,11 +79,19 @@ ERROR - JavetException: Javet library is not loaded because <null>
22879
- [配置选项](#配置选项)
22980
- [支持的主题](#支持的主题)
23081
- [补充说明](#补充说明)
82+
- [版本说明](#版本说明)
83+
- [轻量版的优势](#轻量版的优势)
84+
- [轻量版本缺少的功能](#轻量版本缺少的功能)
85+
- [全量版使用须知](#全量版使用须知)
86+
- [基本使用要求](#基本使用要求)
87+
- [全量版已知问题](#全量版已知问题)
88+
- [问题一解决方案](#问题一解决方案)
23189
- [下载和安装](#下载和安装)
23290
- [稳定版](#稳定版)
23391
- [开发版](#开发版)
23492
- [下载步骤](#下载步骤)
23593
- [开发指南/贡献指南](#开发指南贡献指南)
94+
- [TODO](#todo)
23695
- [许可证](#许可证)
23796

23897
## Finder API 文档
@@ -657,8 +516,140 @@ extraApiRenderFinder.renderCodeHtml(htmlContent)
657516
- 补充说明:
658517
- 双主题模式会生成两个并列的 div 元素
659518

519+
## 版本说明
520+
521+
插件提供两个版本:
522+
523+
- **全量版**:包含所有功能,包括代码高亮等依赖 JS 的相关功能。
524+
- **轻量版**:轻量级版本,不包含 JS 相关功能和相关依赖。
525+
526+
### 轻量版的优势
527+
528+
- 更小的插件体积
529+
- 更快的启动速度
530+
- 更低的内存占用
531+
- 更低的系统性能要求
532+
- 支持全平台(全量版仅支持以下平台:Linux ARM64、Linux x86_64、macOS ARM64、macOS x86_64、Windows x86_64)
533+
534+
### 轻量版本缺少的功能
535+
536+
- 代码高亮(Shiki.js 渲染)
537+
538+
<!-- - 图表渲染(Mermaid)
539+
- 公式渲染(KaTeX) -->
540+
541+
- 其他 JS 运行时相关功能
542+
543+
如果您需要上述功能,请使用全量版。
544+
545+
## 全量版使用须知
546+
547+
⏱️ **首次使用提示**: 全量版的 JavaScript 功能(如 Shiki 代码高亮)在首次调用时需要 1~3 秒进行环境初始化。这是正常现象,之后的调用速度会非常快。
548+
549+
> ⚠️ **重要**: 全量版依赖 Javet 加载 Node.js 原生库(基于 JNI),受 Halo 插件架构限制,存在[已知问题](#全量版已知问题)。
550+
551+
### 基本使用要求
552+
553+
1. **请勿热重载更新**: 请勿直接覆盖更新(如使用应用商店/插件列表的快捷更新操作)
554+
2. **正确的更新流程**:
555+
- 方法一:停止插件 → 卸载插件 → **重启 Halo** → 安装新版本 → 启动插件
556+
- 方法二:停止插件 → 卸载插件 → 安装新版本 → **重启 Halo** → 启动插件
557+
3. **卸载推荐做法**: 在卸载全量版后**重启 Halo** 确保原生库资源完全释放。
558+
559+
### 全量版已知问题
560+
561+
- 问题一:卸载后重新安装全量版插件,不重启就启用。调用 JS 相关 API 时会出现错误:
562+
- **首次安装并启动**: 正常工作
563+
- **禁用后重新启用**: 正常工作
564+
- **卸载后重新安装**: ❌ 会出现 `JavetException: Javet library is not loaded` 错误
565+
- **重启 Halo 后**: 恢复正常工作
566+
567+
#### 问题一解决方案
568+
569+
安装好新版本插件后**先别启用**!
570+
在启用新版本插件之前,请**先重启 Halo CMS**。
571+
572+
未来版本会将引擎作为前置依赖插件,更新本插件不再需要重启。
573+
574+
<details>
575+
<summary>📖 技术原因分析(展开查看详细说明)</summary>
576+
577+
根据错误日志和 Halo 架构分析:
578+
579+
**问题根源**:
580+
581+
1. **Halo 插件架构**: 根据 [Halo 开发文档 - 插件架构](https://docs.halo.run/developer-guide/core/framework), Halo 使用
582+
Spring Plugin Framework 实现插件隔离
583+
- 每个插件拥有独立的 Spring ApplicationContext
584+
- 每个插件使用独立的 classloader 加载资源
585+
- 插件间通过 ExtensionPoint 机制通信
586+
- classloader 完全隔离,无法跨插件共享类或资源
587+
588+
2. **Javet 原生库加载机制**:
589+
- Javet 需要从 JAR 中提取原生库文件(`.dll`/`.so`/`.dylib`)到临时目录
590+
- JVM 通过 JNI 加载这些原生库文件
591+
- 原生库文件一旦加载,会被 JVM 锁定
592+
593+
3. **冲突发生过程**:
594+
- 安装插件时,Javet 提取原生库文件到 `C:\Users\用户名\AppData\Local\Temp\javet\进程ID\`(以 Windows 举例)
595+
- JVM 加载这些文件并锁定
596+
- 卸载插件时,虽然 classloader 被销毁,但原生库文件仍被 JVM 锁定,无法删除
597+
- 重新安装时,Javet 尝试提取新文件到同一位置
598+
- 因为文件被锁定,提取失败
599+
- Javet 初始化失败,报错 `Javet library is not loaded because <null>`
600+
601+
**典型错误日志解读**:
602+
603+
```
604+
WARN - Failed to write to ...libjavet-node-windows-x86_64.v.4.1.7.dll because it is locked
605+
ERROR - Native Library already loaded in another classloader
606+
ERROR - JavetException: Javet library is not loaded because <null>
607+
```
608+
609+
这三条日志清晰地展示了整个失败过程:
610+
611+
1. 尝试写入文件失败(文件被锁定)
612+
2. 检测到库已在其他 classloader 中加载
613+
3. 初始化失败,因为无法提取必要的库文件
614+
615+
**为什么重启有效**:
616+
617+
- 重启 Halo 会终止 JVM 进程
618+
- JVM 终止时会释放所有文件锁
619+
- 临时目录中的原生库文件会被清理
620+
- 新的 Halo 进程启动后,Javet 可以正常提取和加载原生库
621+
622+
**为什么 Javet 文档中提到的 JVM 参数无效**:
623+
624+
`-Djavet.lib.loading.suppress.error=true` 这个参数的作用是:
625+
626+
- 抑制 Javet 在检测到"already loaded in another classloader"时的错误日志
627+
- **但无法解决文件锁定问题**
628+
- 当库文件无法提取时,Javet 根本无法完成初始化
629+
- 因此该参数在这个场景下无效
630+
631+
**架构层面的限制**:
632+
633+
这个问题是 JVM/JNI + 插件 classloader 隔离的固有矛盾:
634+
635+
- Halo 的插件隔离设计保证了安全性和稳定性
636+
- 但也导致原生库这类 JVM 级别资源难以管理
637+
- 类似问题在所有使用 classloader 隔离的插件系统中都存在
638+
- 这不是 Javet 或本插件的 bug,而是架构层面的限制
639+
640+
**相关技术文档**:
641+
642+
- [Javet - Load and Unload](https://www.caoccao.com/Javet/reference/resource_management/load_and_unload.html)
643+
- [Javet Issue #124 - Classloader Reload](https://github.com/caoccao/Javet/issues/124)
644+
- [Halo - Plugin Framework](https://docs.halo.run/developer-guide/core/framework)
645+
646+
</details>
647+
660648
## 下载和安装
661649
650+
全量版和轻量版的区别请看:[版本说明](#版本说明)
651+
使用全量版前请看:[全量版使用须知](#全量版使用须知)
652+
662653
### 稳定版
663654
664655
稳定版通过 GitHub Releases 发布,建议生产环境使用。
@@ -700,6 +691,18 @@ extraApiRenderFinder.renderCodeHtml(htmlContent)
700691
701692
参见 [CONTRIBUTING.md](./CONTRIBUTING.md)
702693
694+
## TODO
695+
696+
<details><summary>展开折叠内容</summary>
697+
698+
- [ ] 提供随机文章 API
699+
- [ ] 提供预计阅读时间 API,及相关配置项
700+
- [ ] 提供图表渲染 API
701+
- [ ] 提供公式渲染 API
702+
- [ ] 分离 Node.js 环境支持为可选前置插件(预计 3.0 版本实现)
703+
704+
</details>
705+
703706
## 许可证
704707
705708
[AGPL-3.0](./LICENSE) © HowieHz

0 commit comments

Comments
 (0)