写在前面
建 KunSpace 的时候,外人看往往觉得:「不就是个个人站吗?」
真动手之后会发现:页面可以很简单,但一旦叠上博客体系、管理后台、AI 助手、音视频工具、国内外双轨部署,难点就不在「会不会写 React」,而在边界条件、浏览器能力、服务端约束,以及个人站必须扛住的工程取舍。
这篇文章只做一件事:把本站真正难的点写清楚——现象是什么、怎么定位、最后怎么解决。
相关前文:
一、难点总览
| 层级 | 最大难点 | 核心解法 |
|---|---|---|
| 框架与渲染 | App Router 下 Server / Client 边界极易踩坑 | 约定「图标与交互放 Client;数据与 SEO 放 Server」 |
| AI 助手 | 幻觉、超时、外部 API 不稳定 | 分流(检索 / 工具 / 模板)+ 限流 + 反幻觉约束 |
| 音视频工具 | 浏览器能力碎片化 + TTS / ffmpeg 体积与打包问题 | Web Audio 本地处理 + Edge TTS 走服务端 + ffmpeg.wasm 按需加载 |
| 部署与运维 | 国内访问、缓存损坏、进程互相抢 .next |
双轨部署 + 清缓存重启 + standalone 注意外部依赖 |
| 体验排障 | 「能打开但点不动」比 500 更难查 | 优先查静态资源是否 404、页面是否完成水合 |
二、框架选型:为什么是 Next.js,难在哪?
2.1 选型本身不难,难在「选完之后的约束」
技术栈大致是:
Next.js 15(App Router)+ TypeScript + Tailwind
内容:Markdown
数据:Upstash Redis / 本地 JSON
LLM:OpenAI 兼容接口(如硅基流动)
部署:海外 Vercel 思路 + 国内腾讯云 Docker / standalone
选 Next.js 的理由很务实:
- 个人站要 SEO:博客、作品页最好能被搜索引擎抓到。
- 既要页面又要接口:留言、统计、小 Kun、TTS,都需要 API Route。
- 和部署生态合拍:纯静态导出不够用,Node 运行时刚好够。
真正的难点不是「Next.js 会不会」,而是 App Router 把渲染模型拆成了两套宇宙:
- Server Component:默认,适合读 Markdown、拼 SEO、少下发 JS。
- Client Component:
"use client",适合事件、录音、Canvas、本地解码。
2.2 最大坑:把「不能过边界的东西」传给了 Client
现象: 工具页线上直接 500。
怎么定位:
- 看服务端日志,而不是只看浏览器 Network。
- 错误指向:RSC 不能把函数(Lucide 图标组件)当 props 传给 Client Component。
- 对照代码:Server 页面把
icon={Braces}传给了"use client"的ToolShell。
怎么解决:
- 列表页可以在 Server 树内渲染图标(同一侧没问题)。
- 工具详情壳子改成 Client 内部用
slug → icon映射,不再从 Server 传入组件引用。 - 每个工具一个
*ToolClient.tsx,页面只负责generateMetadata+ 挂载 Client。
这是我个人认为框架层最大的难点:不是语法,而是边界感。一旦混淆,表现就是「本地偶发正常、线上必挂」。
2.3 配套选型里的小决定
| 点 | 选择 | 原因 |
|---|---|---|
| 样式 | Tailwind | 个人站迭代快,设计 token 用 CSS 变量即可 |
| 动效 | Framer Motion(克制用) | Hero / 氛围可以有,工具页优先稳 |
| 内容 | Markdown + gray-matter | 写博客零后台依赖 |
| 状态数据 | Redis(线上)/ JSON(本地) | 留言、统计、互动不值得上重型数据库 |
三、小 Kun:产品简单,系统并不简单
小 Kun 看起来只是右下角一个聊天框,背后却是整站最「像产品」的子系统。
3.1 难点:幻觉(会编)
访客会问:「站长叫什么?某某角色是谁?」大模型很乐意编一个听起来合理的答案。
怎么解决:
- 硬事实写进系统约束:公开回复里站长姓名只允许固定写法。
- 人名 / 角色走工具或模板:能查就查;查不到就明确说不知道。
- 禁止无证据编造站内关系:没检索到就不提「本站收录」。
细节见:小 Kun 回答逻辑与反幻觉。
3.2 难点:慢与超时
个人站通常是小机器。一次对话如果串行「LLM → 工具 → 再 LLM」,很容易超过网关超时。
怎么解决:
- 公开聊天限流(按访客指纹)。
- 部分问题本地秒回(寒暄、固定事实),不打模型。
- 工具调用做超时与降级;等待态用文案降低焦虑。
- 历史只带最近几轮,控制上下文体积。
3.3 难点:外部工具「免费但不稳定」
天气、百科、汇率、GitHub 等免费 API 常有 CORS、频率限制、格式变动。
怎么解决: 工具层统一封装;失败时给可理解的错误。个人站宁可少一个技能,也不要一个技能拖垮整次对话。需要跨域时,优先走服务端代发,而不是让浏览器直连第三方。
四、音视频在线工具:浏览器里做工程
工具页后来做成音视频一条龙:转 WAV、唤醒语料 TTS、录音、波形频谱、剪切、噪声、延迟、视频抽音频。
4.1 难点:浏览器能力不统一
| 现象 | 原因 | 解法 |
|---|---|---|
| 点录音没反应 | 非安全上下文,或权限被拒,或页面 JS 未加载 | https / localhost;权限提示写清;先查静态资源是否 200 |
| 录音参数过严直接失败 | 部分设备不接受过细的 getUserMedia 约束 |
先用 { audio: true },再在本地转 16k 单声道 |
| 解码 / 导出行为怪异 | Context 生命周期、编码格式差异 | 统一 decode → resample → encodeWav |
统一音频管线:
decodeAudioData
→ OfflineAudioContext 重采样 / 混音
→ 手写 PCM16 WAV 头并导出
唤醒相关默认目标格式:16 kHz 单声道 WAV。
4.2 难点:Edge 在线 TTS 不能稳稳放在浏览器里
唤醒语料要批量生成 WAV,用了 Microsoft Edge 在线 TTS(免 Azure 密钥)。
但浏览器 WebSocket 受限,Next 打包 ws 时还可能出现 mask is not a function。
怎么解决:
- TTS 放在 Node API Route(
/api/tools/wake-tts)。 serverExternalPackages排除错误打包。- 前端把 MP3 转成 16k WAV,再用
fflate打 zip。 - 限流 + 语速 / 音调变化,控制滥用并增加样本多样性。
产品上写清楚:合成时文本会经服务器发给微软;音频下载发生在本地。
4.3 难点:视频抽音频太重
ffmpeg.wasm 体积大。
怎么解决: 按需动态加载 core;工具页注明短视频、首次较慢、本地处理。不把重依赖塞进全站首屏。
4.4 难点:频谱「看起来像坏了」
波形有了、频谱全黑——其实是线性幅度归一化:低频能量过大,中高频被压成背景色。
怎么解决: 频谱改对数(dB)映射;削波检测不要「碰到 0.99 就报警」,改为更接近硬削波的统计判断。
五、部署与工程环境
5.1 国内外双轨
海外与国内访问路径不同,详见 搭建与部署文。
工程注意:output: "standalone" 时,被标成 external 的包(如 msedge-tts)必须进 standalone 的 node_modules,否则线上 TTS 会挂。
5.2 「页面能开,按钮全死」
现象: 页面 200,上传 / 录音没反应;控制台里 chunk 404。
怎么定位: HTML 与 JS 哈希不一致,React 没有完成水合。
常见原因: 多个 next build / next start / next dev 同时搅乱 .next。
怎么解决:
Remove-Item -Recurse -Force .next
npm run dev
# 浏览器强刷
排障顺序建议:
- 静态 chunk 是否 200
- 页面是否已水合
- 再查权限、解码、API 等业务逻辑
5.3 数据与安全上的取舍
| 点 | KunSpace 做法 |
|---|---|
| 访客识别 | hash(IP|UA),无 Cookie;换网络会被算成新人 |
| 管理登录 | 服务端 Cookie 会话 + 环境变量密码 |
| 公开贵接口 | 限流、文本长度限制、可读错误 |
| XSS 风险点 | TTS 文本做 XML escape 再进 SSML |
5.4 性能上的取舍
- 能 Server 渲染的不要整页变 Client。
- 重型能力(ffmpeg)动态加载。
- 频谱分析限制前约 12 秒,避免主线程卡死。
- i18n 用类型约束中英文案键一致,减少漏翻。
六、如果只保留三条经验
- Next.js App Router 最大的税,是 Server / Client 边界。 图标、录音、Canvas,默认按 Client 边界设计,少在 props 里传函数。
- 个人站上的 AI,难点是可信与成本,不是「能不能接上模型」。 分流 + 工具 + 限流,比堆 Prompt 更重要。
- 音视频工具要拥抱浏览器限制。 本地 Web Audio 做主路径;必须联网的能力放服务端;重活按需加载。
七、还没完全解决、但心里有数的事
- 移动端录音 / TTS 体验仍碎。
- Edge TTS 依赖第三方服务策略,存在突然收紧的风险。
- 频谱 / 响度是工程可用级别,不是专业 DAW 计量。
- 小 Kun 外部工具故意保持「少而稳」。
这些不是失败,而是个人站的边界选择:用可控复杂度,换长期养得起。
写在最后
KunSpace 的难,不在某一个 API,而在于它同时想当作品集、可演示的 AI 助手、带专业方向的音视频小工具箱,还要在国内稳定打开。
每一层单独看都不算天文级难题;叠在一起,就会逼你做大量「不起眼但决定成败」的工程决定。
对我自己而言,最管用的习惯就两句:
先分清 Server / Client,先保证 JS 能加载,再谈功能和模型。
评论
还没有评论,来做第一个吧
读完了不评论,作者会以为你在沉思