背景
作为开发者,我们每天都在写 Markdown。但预览工具要么太重(VS Code 300MB+),要么要收费(Typora),要么功能臃肿。
我只想要一个纯粹的预览工具:拖个文件进去,漂亮地渲染出来,改了自动刷新。不需要编辑,不需要插件系统,不需要云同步。
于是我用 Rust 写了一个,最终二进制只有 1.1MB。
技术选型
| 组件 | 选择 | 为什么 |
|---|---|---|
| 语言 | Rust | 零成本抽象,编译后体积小 |
| GUI | wry | 调用系统 WebView,不打包 Chromium |
| Markdown 解析 | pulldown-cmark | 纯 Rust,支持 GFM |
| 代码高亮 | highlight.js | 40+ 语言,内嵌到二进制 |
| 文件监听 | notify | 跨平台文件 watcher |
| 文件对话框 | rfd | 原生系统对话框 |
关键决策:用系统 WebView 而不是 Electron。
macOS 自带 WebKit,Windows 有 WebView2,Linux 有 WebKitGTK。wry 这个库帮你统一了接口,你只需要给它 HTML,它帮你渲染。
结果就是:不需要打包一个 150MB 的 Chromium,二进制直接从 150MB 降到 1MB。
核心代码
Markdown 渲染只需要几行:
use pulldown_cmark::{Options, Parser, html};
fn md_to_html(md: &str) -> String {
let opts = Options::ENABLE_TABLES
| Options::ENABLE_STRIKETHROUGH
| Options::ENABLE_TASKLISTS;
let parser = Parser::new_ext(md, opts);
let mut html_out = String::new();
html::push_html(&mut html_out, parser);
html_out
}
代码高亮用 include_str!() 把 highlight.js 直接嵌进二进制:
const HLJS_JS: &str = include_str!("../assets/hljs/highlight.min.js");
这样完全离线可用,不依赖任何 CDN。
体积优化
Cargo.toml 里的 release profile:
[profile.release]
opt-level = "z" # 优化体积
lto = true # 链接时优化
codegen-units = 1 # 单线程编译,更好优化
strip = true # 去掉调试符号
panic = "abort" # 不要 unwind 代码
最终体积:
- 单架构:1.1MB
- Universal Binary(arm64 + x86_64):2.2MB
- DMG 安装包:1.2MB
对比
| MD Preview | Electron 方案 | |
|---|---|---|
| 二进制 | ~1.1MB | 150+ MB |
| 内存 | ~15MB | 200+ MB |
| 启动 | 秒开 | 2-5 秒 |
| 运行时 | 系统 WebView | 打包 Chromium |
功能
- 拖放 / Cmd+O / 命令行打开
- 文件修改自动刷新
- 40+ 语言代码高亮(离线)
- 暗色模式跟随系统
- GFM 表格、任务列表、删除线
- macOS 双击 .md 文件关联打开
开源
MIT 协议,欢迎 Star 和 PR。
如果你也受够了臃肿的 Markdown 工具,试试这个 1MB 的方案。