AetherBlog 目前是一个纯 Web 架构的产品:
apps/blog/ — Next.js 15 + App Router,面向读者apps/admin/ — Vite + React 19 + react-router-dom,面向作者/运营apps/server-go/ (Go/Echo) + apps/ai-service/ (FastAPI)你的问题是:怎么把这套东西变成 iOS / Mac / Windows 的 App?是换技术栈还是做代码转换?
结论先说:你不需要换技术栈,也不需要"代码转换"。当前的 React/Next.js 代码可以被多个"外壳"工具直接复用。
| 决策点 | 你的选择 | 对方案的影响 |
|---|---|---|
| 应用优先级 | Blog + Admin 都做,并行推进 | 执行 3 个阶段全量 |
| iOS App Store | 上 | Blog + Admin 都做 Capacitor iOS,走原生能力加持(推送/离线)规避 Apple 4.2.2 审核 |
| Google Play | 上 | Capacitor Android 同步产出 |
| Mac App Store | 不上 | Tauri 2 直接出 .dmg,官网下载 + Apple notarize |
| Microsoft Store | 不上 | Tauri 2 直接出 .msi/.exe,官网下载 + Code Signing 证书 |
| 人力 | 单人全职 | 排期按 7 天/周节奏,下面给到周级甘特 |
总工期估算:6-9 周 上线所有四端。
分层策略 — 用最轻的工具覆盖最大的需求:
| 阶段 | 目标 | 工具 | 工期估算 | 新技术栈 |
|---|---|---|---|---|
| 0. PWA 基线 | Blog 可"添加到主屏幕",iOS/Android/桌面都能装 | next-pwa + Web App Manifest | 3-5 天 | 无(纯 Web) |
| 1. 移动端 App | Blog + Admin 发布到 iOS App Store / Google Play | Capacitor 6 | 2-4 周 | 少量 Swift/Kotlin 配置,无需写原生 UI |
| 2. 桌面端 App | Admin 变成 macOS / Windows 原生写作 App,官网下载分发 | Tauri 2 | 2-3 周 | 少量 Rust 配置,无需写原生 UI |
| 3(可选). 深度原生化 | 纯 Swift/SwiftUI 重写 Blog 阅读器 | SwiftUI / Kotlin Compose | 2-4 月 | 只有在数据证明值得时才做 |
| 周 | 主线任务 | 交付物 | 并行副线 |
|---|---|---|---|
| W1 | PWA 基线 + 痛点预处理 | Blog 可装;axios 改 Bearer;ISR 方案定稿 | 申请 Apple Developer 99/GooglePlay25(审核需要 1-3 天) |
| W2 | Blog Capacitor iOS 集成 | iOS 模拟器能跑通登录/读文章/SSE | 申请 Windows Code Signing 证书(签发 3-5 天) |
| W3 | Blog Capacitor Android + 推送/离线/分享插件 | 真机跑通,推送链路可用 | Apple notarize 配置 |
| W4 | Admin Capacitor 集成(iOS + Android) | Admin 移动端可登录/写作/上传图片 | App Store 素材(截图/描述/隐私政策)准备 |
| W5 | Admin Tauri 2 桌面集成 | macOS .dmg + Windows .msi 本地可跑 | iOS Blog 提审,进入 Apple 审核队列 |
| W6 | Tauri 原生能力(菜单/托盘/快捷键/本地草稿) | 桌面端功能完备 | 处理 App Store 首轮审核意见 |
| W7 | Tauri 代码签名 + notarize + 官网下载页 | aetherblog.com/download 上线 | Blog Android 发 Google Play |
| W8 | Admin iOS / Android 提审 | Admin 四端齐备 | 回归测试、自动化 CI |
| W9 | 缓冲 / 审核驳回迭代 / 文档 | 全部上线 | 用户反馈迭代 |
关键路径风险点(按概率降序):
output: 'export' + revalidate 冲突)→ W1 必须定稿核心判断依据:
apps/blog 和 apps/admin 的所有页面用 RN/Flutter 重画一遍content-visibility 优化)要在 RN 里重做 — 基本等于做两套 UI目标: 让 Blog 可以在 iOS/Android/桌面浏览器"添加到主屏幕"并离线浏览已读文章。
做什么:
apps/blog/ 已有 app/manifest.ts(事实报告 §1),完善图标/短名/描述next-pwa 或手写 Service Worker:
stale-while-revalidate、图片 cache-first、API network-firstapple-touch-icon、apple-mobile-web-app-title — layout.tsx 第 36-79 行已有 appleWebApp.capableSearchPanel.tsx 的 EventSource 在断网时没有降级 → 加 try/catch + fallback 到非流式 API产出:
价值:
目标: Blog 和 Admin 各有 iOS/Android App,可上 App Store / Google Play。
Capacitor 是什么:
.next/ 或 dist/)打包进一个原生 App 壳,App 启动时加载本地 HTML/JS/CSS,通过 Native Bridge 调用摄像头/推送/文件系统为什么选 Capacitor 而不是其他 WebView 框架:
| 方案 | 优点 | 致命缺点 |
|---|---|---|
| Capacitor 6 ✅ | 官方支持 Next.js Static Export;插件生态最成熟;Ionic 商业公司长期维护;iOS/Android/Web 三端统一 | 产物偏大(~20MB) |
| Cordova | 历史包袱重 | 2024 后社区活跃度断崖;插件老旧 |
| Tauri Mobile | Rust,体积小 | 2026 仍是 beta 质量;插件少;Next.js 适配不完善 |
| Expo + React Native | 生态好 | 需要重写所有 UI;不适合你 |
实施步骤(Blog 为例):
# 1. 把 Next.js 改成静态导出(或用 @capacitor/next 桥接 SSR)
# apps/blog/next.config.ts 加 output: 'export'
# 但要先处理 ISR 页面(事实报告 §5 痛点 3)
# 2. 安装 Capacitor
cd apps/blog
pnpm add @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android
# 3. 初始化
pnpm cap init "AetherBlog" "com.aetherblog.reader" --web-dir=out
# 4. 构建并同步
pnpm build && pnpm cap sync
# 5. 打开 Xcode / Android Studio
pnpm cap open ios
pnpm cap open android你需要处理的事实报告里的痛点:
| 痛点 | 解决方案 |
|---|---|
痛点 1:withCredentials cookie 在 WKWebView 跨域限制 | 切换到 Bearer Token in Authorization header,后端已经是 JWT — 改前端 axios 拦截器,移除 withCredentials |
| 痛点 3:Next.js ISR 与静态导出冲突 | 把页面改成纯 CSR('use client' + useEffect fetch),或用 next export + API 全部走客户端;博客列表本来就是数据驱动的,改造量小 |
| 痛点 4:EventSource 在 iOS 15 以前有超时 | Capacitor 里 WKWebView 继承系统版本;App Store 最低 iOS 14 的话要加 fetch 流式 polyfill |
痛点 5:next/image 优化端点 | 改用后端 Go 服务的图片代理(你已经有 pkg/image 包),或直接出 CDN URL |
| 痛点 2:API 地址配置 | apps/admin/src/services/api.ts 的 VITE_API_URL 在 App 里改为绝对地址指向生产后端 https://aetherblog.com/api |
原生能力加分项(Capacitor 插件直装):
@capacitor/push-notifications — 文章更新推送@capacitor/share — 分享文章到微信/Twitter@capacitor/haptics — 触觉反馈(匹配 Aether Codex 的"手感"哲学)@capacitor/app — 深层链接(点通知打开指定文章)@capacitor/filesystem — 离线文章缓存@capacitor/preferences — 替代 localStorage 用原生 KV(解决痛点 2、7)发布到 App Store:
估算工期(单人):
目标: Admin 变成 AetherBlog Studio.app (macOS) 和 AetherBlog Studio.exe (Windows)。
为什么桌面端选 Tauri 2 而不是 Capacitor / Electron:
| 指标 | Tauri 2 | Electron | Capacitor Desktop |
|---|---|---|---|
| 包体积 | ~10MB | ~150MB | ~80MB |
| 内存占用 | ~60MB | ~250MB | ~150MB |
| 启动速度 | ~300ms | ~1.5s | ~800ms |
| 原生系统集成 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| 使用系统 WebView | ✅(Safari/Edge) | ❌ 自带 Chromium | ❌ 自带 Chromium |
| 需要学新语言 | Rust(但很少写) | 不需要 | 不需要 |
| 生态成熟度(桌面) | ⭐⭐⭐⭐(2024 1.0,2025 2.0) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
Tauri 的原理:
apps/admin/dist)打包进 Tauri 壳invoke() 调用 Rust 函数处理文件系统、系统托盘、全局快捷键等实施步骤:
# 1. 在 Admin 根目录装 Tauri CLI
cd apps/admin
pnpm add -D @tauri-apps/cli @tauri-apps/api
# 2. 初始化
pnpm tauri init
# 配置:
# - App name: AetherBlog Studio
# - Window title: AetherBlog Studio
# - Web assets: ../dist
# - Dev URL: http://localhost:5173
# - Build cmd: pnpm build
# 3. 开发模式
pnpm tauri dev
# 4. 打包
pnpm tauri build
# 输出:
# - macOS: .app / .dmg
# - Windows: .msi / .exe桌面端独有的加分项:
⌘⇧N 全局新建文章,即使 App 最小化.surface-raised 设计需要处理的事实:
packages/editor 的 CodeMirror Markdown 编辑器在桌面端体验会显著优于移动端发布:
估算工期(单人):
什么时候考虑:
做什么:
这是另一份报告的话题,现在不必规划。
按阶段排序:
apps/blog/app/manifest.ts — 完善 icons / shortcutsapps/blog/app/layout.tsx — 补齐 Apple metaapps/blog/public/sw.js — 新建 Service Worker(或用 next-pwa 插件自动生成)apps/blog/next.config.ts — 注册 PWA 插件apps/blog/capacitor.config.ts — 新建apps/blog/ios/ / apps/blog/android/ — 新建原生壳目录apps/blog/next.config.ts — 改 output: 'export',处理 ISR 页面apps/blog/app/lib/api.ts — API URL 支持绝对地址apps/admin/src/services/api.ts — 移除 withCredentials,改纯 Bearer Tokenapps/blog/app/components/SearchPanel.tsx — EventSource 降级处理apps/blog/app/components/MarkdownRenderer.tsx — next/image → CDN 直出apps/admin/src-tauri/ — 新建 Rust 侧代码apps/admin/src-tauri/Cargo.toml — Rust 依赖apps/admin/src-tauri/tauri.conf.json — 窗口/菜单/权限配置apps/admin/vite.config.ts — 增加 Tauri dev server 配置apps/admin/src/components/common/CommandPalette.tsx — 桌面端额外增加系统级命令完整事实报告见上一步 Explore agent 的输出。以下是与本方案直接相关的关键结论:
✅ 基础设施已就绪:
manifest.ts + Apple metajwt_secrets 表 + 定时轮换),天然适配原生 Appnext.config.ts 已用 viewTransition 和 output: 'standalone'/api,Gateway 模式 (start.sh --gateway) 架构已验证MobileMenu / MobileBottomPullNav / useMediaQuery)⚠️ 要改的地方:
withCredentials: true → 改 Bearer Tokenrevalidate = 300-600) 与静态导出冲突 — 需评估改造成本SearchPanel.tsx)需加 WKWebView 兼容降级localStorage 大量使用(主题、搜索历史、时间线展开状态)在 App 里要迁移到 @capacitor/preferences❌ 不可行的快捷方式:
每个阶段结束后怎么确认"做完了":
阶段 0 验证:
cd apps/blog && pnpm build
# 用 Lighthouse PWA 审计 http://localhost:3000 应该拿到 90+
# iOS Safari 访问后能从"分享菜单"看到"添加到主屏幕"阶段 1 验证:
cd apps/blog
pnpm cap run ios # Xcode 模拟器运行
pnpm cap run android # Android Studio 模拟器运行
# 测试:登录、读文章、离线看已读文章、收到推送、系统分享阶段 2 验证:
cd apps/admin
pnpm tauri dev # 本地启动
pnpm tauri build # 打包
# 测试:⌘N 新建文章、系统菜单、托盘图标、本地草稿自动保存、断网写作、代码签名| 项目 | 阶段 0 | 阶段 1 | 阶段 2 | 阶段 3 |
|---|---|---|---|---|
| 开发工期(单人) | 3-5 天 | 2-4 周 | 2-3 周 | 2-4 月 |
| 硬性费用 | 0 | Apple Dev 99/年+GooglePlay25 一次 | Apple Dev 99/年+Windows代码签名200/年 | 同阶段 1+2 |
| 新学习技术 | Service Worker | Capacitor + Xcode + Android Studio 基础 | Tauri + Rust(少量) | SwiftUI + Kotlin Compose |
| 维护成本 | 低 | 中(每年跟随 iOS/Android 新版本) | 低 | 高(双倍代码) |
最划算的路径: 如果你只有 1 个月人力预算 → 做阶段 0 + 阶段 2(PWA + 桌面 Admin),跳过 App Store 的复杂度,直接拿到一个"可安装的 Web"+"专业的桌面写作 App"。App Store 等有稳定用户反馈后再做。
加载评论中...