把 WebView2 渲染换成原生轻量渲染,把任何下载劫持到 IDM / aria2 的通用框架。
现在这份代码是从一个具体诉求长出来的(Axolotl Launcher 空载 540 MB、下载龟速),但它不是某个启动器的补丁 —— 它是一层可以套在任意 Tauri / WebView2 应用外面的壳。
原版 Axolotl 空载 7 进程 / 540.5 MB (其中 WebView2 6 个进程 439.6 MB,占 81%)
noweb 原生外壳 (见 docs/00-baseline.md 与 out/ 下的实测 JSON)
| 能力 | 怎么做到 | 代价 / 边界 |
|---|---|---|
| 换渲染(零编译依赖) | 用 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=N 拉起目标应用,CDP 接上,原生窗口做 UI,命令经 CDP 转发给它的后端 |
它的 WebView2 进程还在(隐藏后可见内存下降,但不归零) |
| 换渲染(真省内存) | 完全不启动 WebView2,直接读应用自己的数据面(SQLite / JSON) | 需要一个 profile 适配器;不能改它的状态,只能读 + 委托 |
| 注入自己的设置面板 | CDP Page.addScriptToEvaluateOnNewDocument 把面板装进它自己的页面,刷新也在 |
需要能控制它的启动参数(或它自己开了调试口) |
| 任何下载→外部下载器 | 面板/拦截器检测大文件请求 → 回环 hook → aria2.addUri / IDMan.exe / 任意命令模板 |
需要应用确实走 HTTP,且我们能碰到那次请求 |
| 命令面自动发现 | 扫它自己前端资源里的 invoke("命令名") 调用点 |
编译/混淆过的包可能找不到全部命令 |
没做的事,不假装做了:
- ❌ 免重编译地把 Tauri 应用的 WebView2 替换成原生渲染器。Tauri 2 的
wry静态链接 WebView2Loader, 没有代理 DLL 的口子;进程内换渲染器只能改它的 Rust 代码。 我们给的是「原生 UI + 隐藏它的渲染窗口 + 复用它的后端命令」和「完全绕开它读数据面」两条真路。 - ❌ IDM 的端到端实测。本机 IDM 未安装(只剩两个残留 DLL),代码与参数构造有单测,装完即可用,
但我不声称在这台机器上验证过。见
docs/00-baseline.md§5。
| 策略 | 内存 | 通用性 | 适用 |
|---|---|---|---|
DomOverlay |
不变 | ★★★ 任意 WebView2 应用 | 只想把下载接管过来、加个面板 |
CdpShell |
可见内存下降 | ★★★ 任意 Tauri/WebView2 应用 | 想要原生 UI,但应用后端逻辑复杂到不想重写 |
NativeDataPlane |
真正归零 | ★ 需要 profile | 应用的数据面开放(Axolotl 就是) |
NativeDataPlane 已经在 crates/noweb-adapter-axolotl 里落地:只读 app.db,列存在性全探测,
不启动 Chromium,读的是真实数据(本机实测 5 个实例、8 个 Java、download_engine=legacy、
max_concurrent_downloads=256)。
# 依赖:Rust(本机装在 D:\rustup / D:\cargo)+ MSVC Build Tools
cd D:\ku\traecode\axl-fastgui
cargo build --release # 首次较久(~250 个包)
# 原生外壳
.\target\release\noweb.exe
# 命令行:看本机到底有哪些下载引擎可用(只报探测到的事实)
.\target\release\noweb-dl.exe probe
# 换来换去看速度差多少(这是下载效率的判据,不是嘴上的)
.\target\release\noweb-dl.exe bench <url> --splits 16 --json out\download-bench.json只想验证下载桥,不想要 GUI:把 noweb-dl.exe 单独拷走也行,它只依赖系统。
crates/
noweb-protocol/ 稳定契约:Command / Event / Capabilities / 三代策略枚举
noweb-download/ 下载桥:aria2 RPC · IDM · 命令模板 · 内置兜底(含 noweb-dl CLI)
noweb-cdp/ CDP 客户端(手写最小 WebSocket)+ 注入器 + 回环 hook 服务
noweb-adapter-axolotl/ Axolotl profile:只读 app.db(NativeDataPlane)
noweb-adapter-tauri/ 通用 Tauri/WebView2 接管:宿主发现、调试口、隐藏窗口
noweb-ui/ egui 原生外壳(实例 / 下载 / 接管 / 设置 / 日志)
docs/
00-baseline.md 实测基线(原版内存、上游结构、数据面、网络、环境约束)
01-architecture.md 架构与更新抗性设计
02-update-playbook.md 上游发版时怎么跟(本框架存在的理由)
upstream/
PIN.toml 上游 pin(commit / 版本 / 探测时间)
capabilities.json 上次探测到的能力清单,用于 diff
scripts/
measure-memory.ps1 内存对比(同一判据)
measure-download.ps1 下载速度对比(单连接 vs aria2)
probe_axl_db.py 只读 dump app.db 结构
dump_axl_rows.py 只读 dump 实例/Java/设置
Axolotl 是 Rust + Tauri 2 + Vue 3,849 个 cargo 包,几乎每天推 main。
所以本项目的铁律是:UI 的依赖树里没有 tauri / theseus / webview2。
| 上游动了 | 我们的反应 |
|---|---|
| 前端页面/组件 | 不用管(我们不在它的渲染层里) |
| 新增一个 Tauri 命令 | noweb-dl/UI 不用重编;能力清单多一项,UI 认识的照旧显示,不认识的走兜底 |
app.db 加列/改列 |
不用管(pragma table_info 存在性检测,缺列给默认值) |
| 换存储 / 加新表 | profile 返回空 + 明确错误信息,UI 显示原因而不是白屏 |
| 大版本重构 Rust 侧 | 只有 noweb-adapter-* 需要动,noweb-ui 与 noweb-protocol 不动 |
详细流程见 docs/02-update-playbook.md。
- 只读被接管应用的数据:
app.db用SQLITE_OPEN_READ_ONLY,绝不写它的任何文件。 - 隐藏窗口是可逆操作(
显示窗口按钮 / 重启应用即恢复)。 - hook 服务只监听
127.0.0.1,且只做三件事:ping、handoff、settings。 - 注入的 JS 全部
try/catch包裹:hook 连不上时不会把宿主页面搞崩。
MIT(本框架自身)。被接管应用各自遵循其原许可(Axolotl 为 GPL-3.0-only)—— 本框架不复制、不修改、不再分发上游代码。