1. 缘起
在国内网络环境下,我发现插件、主题在检查更新的时候非常慢,走代理之后就非常顺畅,这让我好奇 Obsidian 的插件管理逻辑是怎么样的。
2. 定性分析
Obsidian Plugin 都是通过 Github 做 Release 的,结合这个条件和上面看到现象可以得到一个结论,这个问题应该是国内用户特有的,本质原因跟 go packages、Rust crates 访问慢的问题是一致的。
由此引发了另外一个问题,如果下载 Obsidian Plugin Release Package 慢可以理解,但是检查更新也缓慢就有点奇怪,是什么原因导致检查更新也变慢了。
3. 定量分析
Obsidian 的技术栈主要是 electron、javascript、typescript 等,涉及到很多的 Web 开发知识,这并不是我擅长的。所以我不打算从代码级别来分析碰到问题,我打算从自己目前掌握的 Web 相关的技术知识尝试分析,试着看能否解决这个问题。
3.1 Obsidian 插件文档
首先从 Obsidian 官方给出的插件开发文档入手,先了解 Obsidian Plugin 开发的基本情况。
3.1.1 Obsidian 插件开发技术要求
- Electron
- Nodejs
- TypeScript
- JavaScript
- Git
- VS Code
3.1.2 Obsidian 社区插件管理流程
- 基础开发环境准备(nodejs、typescript、git、github 账号等)
- 在 github 上 fork Obsidian 提供的 Sample Plugin
- 研发插件,并按照格式维护 manifest.json
- PR 提交插件到 Obsidian 社区进行 review,主要是维护 community-plugin.json 文件
3.2 调试插件管理逻辑
大致思路是通过 DevTools 观查插件更新检查的网络活动,通过网络请求数据结合相关的 javascript 代码分析插件的管理逻辑。
3.2.1 查询插件更新按钮的 HTML 元素
通过 DevTools 的 HTML 元素选择器确认插件更新按钮的 attribute:
确认按钮的 class 属性是 'mod-cta'
。
3.2.2 观测插件更新按钮的网络活动
尝试在 DevTools 的 Network Tab 中观察能够捕捉到点击,如下图所示:
很遗憾没有能够捕捉到任何网络活动,不太确定点击检查更新按钮之后的网络活动应该如何监测。
3.2.3 分析插件更新 callback 代码
目前看来想尝试 Debug 分析出插件管理逻辑有点困难,比较幸运的是可以通过 DevTools Application 中查看源码,从过阅读按钮的 callback 源码分析清楚插件管理的逻辑。查看下面的源码阅读 comments:
3.3 插件管理逻辑总结
- obsidian 将读取 community-plugins.json 中的插件列表。
- 插件的 name、author、description 字段用于搜索。
- 当用户打开插件的详细信息页面时,Obsidian 将从对应的 GitHub 存储库中提取 manifest.json 和 README.md。
- 插件 repo 中的 manifest.json 将仅用于找出最新版本,实际的文件是从插件的 GitHub Release 中获取的。
- 如果 manifest.json 需要比正在运行的应用程序更高的 Obsidian 版本,obsidian 的 versions.json 将被查询以找到兼容的最新版本的插件。
- 当用户选择安装您的插件时,Obsidian 将查找与 manifest.json 中的版本标记相同的 GitHub 版本。
- Obsidian 将下载 manifest.json、main.js 和 styles.css(如果可用),并将它们存储在保险库内的适当位置。
- 当点击插件更新检查按钮的时候,Obsidian 会根据本地的插件列表遍历对应插件 repo 中 manifest.json 以确实当前本地的插件是否是最新版本。
4. 社区方案分析
关于 obsidian 插件管理有一个插件解决方案:TfTHacker/obsidian42-brat: BRAT,虽然它的初衷是帮助做插件 beta 版本的测试管理,不过里面也涉及到了插件自动更新管理的事情,这里做一个简单分析总结(主要是阅读源码 BetaPlugins.ts):
- BRAT 插件更新检查相关的函数调用链:
| -- checkForUpdatesAndInstallUpdates() ---->
| -- updatePlugin() ---->
| -- addPlugin() ---->
| -- |
| -- | -- this.plugin.app.vault.adapter.read() ---->
| -- | -- getRelease() ---->
| -- | -- |
| -- | -- | -- getAllReleaseFiles() ---->
| -- | -- | -- |
| -- | -- | -- | -- grabReleaseFileFromRepository()
2. 检查是否需要更新的关键逻辑是:对比本地的 manifest.json(manifest-beta.json) 文件中的版本与 Github Release 中的 manifest.json 的 version 字段,从而确实是否需要更新(根据上面的函数调用链结合源码阅读非常清楚的看到 BRAT 管理插件更细的逻辑)。
5. 问题总结
obsidian 检查是否有插件需要更新之所以缓慢,是因为在检查更新的过程中涉及到访问如下域名:
- raw.githubcontent.com
- github.com
这些域名访问会有网络速度很慢的问题,所以解决前文提到的检查插件更新慢的原因需要从这个根因入手。
6. what's next
- 解决 obsidian 自带的插件管理逻辑检查更新和下载插件慢的问题;
- 解决强迫症患者问题,老是想点一下看看有没有插件需要更新,例如自动更新;
- 增加回滚插件版本的能力支持;
References
- Obsidian Plugin Developer Docs
- obsidianmd/obsidian-plugin-docs
- TfTHacker/obsidian42-brat: BRAT