Kimi K3 重构10000行单文件屎山代码!

作者:技术拾光

时间:2026-07-23

浏览:327

一个近万行的单文件导致AI上下文token消耗异常严重,KimiK3模型经过深入分析后建议按i18n、CLIbridge等模块顺序进行增量拆分,每次拆分任务可节省80%以上token成本,并显著提升AI读写准确性与效率,从而有效降低整体运营成本。

文章目录

Vibe Coding 的“恶果”终于来了。

最近在升级 JClaude 时,发现 token 消耗异常迅猛。一查代码,好家伙,有个文件已接近一万行。粗略估算,仅这一个文件,上下文就占用了十几万 token。

虽然程序运行完全正常,但技术债越积越厚,不得不改。恰逢近期在测试 Kimi K3,索性把这个任务交给它。这次测试,比做动画效果更有实际意义。

下面就来具体看看,它是如何重构的,结果又如何。

1、项目简介

先简单介绍项目背景:

之前开发了一个 Claude Code 中文界面版,完全克隆了 Claude 桌面版的界面,并调用 Claude Code 终端,自动接入第三方模型。这意味着第三方模型可以直接使用 Anthropic 最强编程智能体,不受账号限制。如果接入 Opus 4.8,该软件的能力基本等同于 Anthropic 官方 Claude 桌面版。

最近添加了角色和技能相关功能,结果发现项目文件已经膨胀到无法忍受。

该项目最初只是一个简单的界面克隆测试,因此代码结构从未被重视。后续不断修改,也未强制要求重构,AI 就这样一路堆砌“屎山”过来。估计很多 Vibe Coding 项目都会面临同样的问题——刚开始只是试试水,玩嗨了就越改越大。

2、基础情况

项目采用 Tauri + Rust 开发,安装包小,内存开销低,可打出多平台发行包。界面部分主要由 JS、CSS、HTML 等前端代码构成,效果出色;后端是 Rust,与系统交互效率高。开发支持热更新,效率不错。

要重构,首先要摸清代码底细。对话由此开始:

然后得到如下结果:

从中可以看到,main.js 已达 9338 行,接近一万行,内部塞了 400 个函数!

接下来具体看看其中内容。

main.js 内部结构

它本身是一个纯 script,没有 import,也没有模块化,仅靠 30 个 // ==== 注释来分段。最大的几个段落:

  • Claude Code CLI bridge —— 约 2160 行,是最大的单一块
  • Experts & Skills 管理 —— 约 800 行
  • i18n —— 约 620 行,基本是翻译数据
  • Code workspace panels / Projects / Settings / Providers —— 各 500-600 行

模块划分还算清晰,但文件确实过于庞大。

是否有优化必要?

基本情况摸清后,K3 给出的结论是:有必要,但需根据后续开发节奏决定,且不建议一次性大改。

支持拆分的理由很明确:

  • 单文件 9k+ 行已超过可维护性的常见阈值,多人协作时合并冲突几乎不可避免
  • 部分段落是天然的拆分候选,成本低收益高:i18n 是纯数据,可抽成 i18n/zh.json、i18n/en.json 等,零风险;CLI bridge 2000+ 行自成一体,抽成独立模块后主文件立刻瘦身 1/4;Tauri 支持原生 ES modules,拆

它提到一个关键点:多人协作时冲突是大问题。不过对我而言还好,毕竟我是多 AI 合作,一把梭。

需要权衡的点:

  • 目前测试覆盖很薄,大重构缺乏安全网,回归风险高
  • 大文件本身不是病——如果这段代码已经稳定、很少改动,靠分段注释导航也能用

建议的优先级:如果近期要持续加功能(尤其是 CLI bridge、Skills 相关),就按 “i18n → CLI bridge → 各 workspace 面板” 的顺序增量抽取,每抽一块运行一遍现有测试;如果只是维护期、改动少,可以先不动,只把 i18n 数据分离出去。

3、多维度分析

从目前情况看,除了大,没有太严重的问题。但比较令人担忧的是,大文件下 AI 读写和 token 消耗问题。所以第二轮需求直接抛给了它:

以下是 K3 的分析结果。

1、代码设计角度

main.js 的问题不仅是“长”,而是无模块化的那种长——400 个函数全都在全局作用域里,依靠一个全局 state 对象和 DOM id 隐式耦合。你无法只改“设置”而不碰“对话”,因为它们共享同一片命名空间。这直接导致可测试性差——那 3 个针对性测试,很大程度上是这种结构的结果,而非原因。函数无法单独 import,就无法进行单元测试。lib.rs 同样是 4148 行单文件,但 Rust 有模块系统和编译器兜底,拆分安全且容易,风险远低于 main.js。styles.css 4836 行在 CSS 中不算异常,危害最低,可放在最后处理。

单从代码设计看,有必要拆,但属于“慢性病”,不致命。

2、AI 读写角度

这是大文件代价最直观的体现:

  • 读不完整:主流 AI 工具单次读文件上限大约 1000 行,一个 9338 行的文件,AI 永远只能看到局部。修改一个功能时,它读到目标段落,却看不到 3000 行外那个依赖同一全局状态的函数——改坏联动的概率显著上升。
  • 编辑易误伤:AI 编辑依赖精确字符串匹配。9k 行文件中相似代码片段多(比如那 14 个并排且结构几乎一样的 persistXxx() 函数),匹配唯一性差,误替换风险高。
  • 定位成本高:目前靠 // ==== 分段标记 + grep 还能工作,但跨段依赖(全局 state、跨段调用)对 AI 不可见,每次都需要重新摸索。

拆成模块后,每个文件能被 AI 一次整读,心智模型完整,改动质量明显提升。

3、Token 消耗角度

按中英文混合代码大约 3.5 字节/token 来估算:

  • main.js 全量读入 ≈ 13 万 tokens,一次就占掉大半个上下文窗口。
  • 实际工作模式是 grep + 分页读取若干段,但每次任务往往需要读取 state 定义段 + 目标功能段 + 相关 persist/i18n 段,累计轻松达到 3-5 万 tokens,而且每次会话都会重复消耗。
  • 拆成模块后,一个任务通常只需整读 1-2 个相关文件(几千 tokens),单次任务节省 80%+,且是持续性收益——每次让 AI 改代码都在省钱。
  • i18n 那 620 行是纯数据,最冤:经常被卷入上下文,却几乎不需要全部内容。

这确实是个大问题,太浪费了。改完能省 80%,这个诱惑可不小。

4、综合判断

单看代码设计,拆分是“应该做但不紧急”;叠加 AI 读写和 token 成本后,必要性明显升级——毕竟主要就是用 AI 辅助开发,大文件的税是每次任务都在交的。

结论不变:增量拆分,顺序 i18n → CLI bridge → 各面板。

4、深入分析

其实心里早有数,因为之前已经让 Opus 4.8 拆过一次。这次很明显也是按拆分方向走。为了谨慎起见,也为了更好引导 K3 完成任务,又问了第三个问题:

1、怎么拆

对齐现有分段,分层 + 自下而上。加载方式从

  • 第 0 层(纯数据,零依赖):i18n、DEFAULTS、MODEL_BLURB/system prompt、action chip prompts
  • 第 1 层(基础):state(全局 state + KEYS + 14 个 persistXxx)、storage、Tauri API 封装
  • 第 2 层(UI 基建):theme、sidebar、tooltip、菜单
  • 第 3 层(功能域):chat、projects、settings、providers、experts/skills、code panels、CLI bridge、browser、code stats、mentions
  • main.js 最终只剩入口:import + init/boot 顺序

2、颗粒度

一个分段一个模块,200–800 行/单文件:

  • 目标:每个文件能被人或 AI 一次整读(<1000 行),预计拆出 15–20 个文件,收进 src/js/ 之类的子目录。
  • 不要再细:拆成 50 个 100 行的小文件会让 import 清单本身变成维护负担,跨文件跳转反而更累。
  • 也别贪全:chat/projects/settings 核心段耦合最重,如果拆到那里发现代价陡增,留一个较大的 app.js(2000 行以内)也完全可以接受——80% 的收益来自前 20% 的抽取。

3、注意事项(按翻车概率排序)

  1. 测试 eval 耦合:如上所述,搬 DEFAULT_EXPERTS 等被测代码块时必须同步改测试的 SRC 路径,标记字符串原样保留。
  2. 循环依赖:功能模块间必然互相调用(chat workspace projects)。ESM 循环导入在“仅运行期调用、无顶层副作用”下是安全的——所以搬移时保持 function foo() {} 声明形式(有提升),禁止在模块顶层执行跨模块调用,init 统一由 main.js 触发。
  3. 共享 state 唯一性:state 对象(main.js:474)必须从 state.js 导出同一个引用,所有模块 import 它,绝不能复制。
  4. 只搬不改:每次提交只做机械搬移 + 补 import/export,不顺手优化逻辑。重构成败的关键就是 diff 可审查。
  5. import 清单遗漏:400 个函数分散后,漏一个 import 就是运行期 ReferenceError,静态检查抓不住(项目无 lint)。对策见下。
  6. init 顺序:boot splash、applyWorkspace 等有 DOM 时机依赖(index.html 注释专门提过),入口处的初始化顺序原样保留。

虽然只是拆一个文件,其实难度不小。因为不同模块之间是有耦合的,之前让 Opus 分析过,有些模块间的耦合度高达几十个。一个拆完之后,文件行数和文件数量都会变化,所以模型必须重新学习新的结构,再进行后续的解耦。

4、如何保障成功

这一点很关键:

  • 试点先行:第一步只做 i18n + state 两段,跑通“搬移 → 改测试 → 验证”全流程,确认模式可行再批量搬。
  • 每步三道闸:npm test 全绿(3 个 node 测试 + cargo test)→ npm run dev 启动冒烟(主界面、聊天、设置、Code workspace 各点一遍,看控制台报错)→ 独立 commit。出问题单步回退即可。
  • 明确的完成标准:main.js 只剩入口(<300 行)、测试全绿、冒烟清单通过、每个被搬分段都能在新文件里被 grep 到。
  • 顺序:i18n → 纯数据 → state/storage → UI 基建 → CLI bridge(最大但自成一体,瘦 1/4 就靠它)→ experts/skills、code panels、browser → 核心段(视情况收尾)。

从它的回答看,理解得比较透彻。经过三轮引导,它已经掌握了关键信息。所以,最后一句话就是:开干!

5、重构过程

下图是它自己做的 todo 任务列表:

改完之后,它又问了两个问题:

第一个是用 git 管理版本,方便回退。第二个是冒烟测试怎么做。这个还是很稳的!

但对它的测试选项不太满意,怎么可以把手动启动 dev 放在推荐位呢?必须你来启动,我来看着啊!

另外说个细节,可以作为对比参考。Opus 4.8 改的时候,虽然改得很细,但很自信地说它会自己做 dev 测试,完全做了个甩手掌柜。

由于第一轮独立性比较强,整体修改非常快。测试了一下,没有太大问题。唯一的问题是没法调用 Claude Code!

不确定它为什么把内置 CC 跳过了,正常没有理由弹这个的。把情况给它说了一下,它成功解决了问题。那就没啥大问题了,继续推进!

随着修改的深入,逐渐变得复杂起来了。改到中间环节的时候,验证点逐渐变多了,修改的时间也越来越久了。

6、重构结果

整个重构过程大概消耗了小半天时间。最后把这个 main.js 从 9938 行压缩到了 263 行,减少 97%。

全部改成模块化设计,拆成了 24 个模块,每个 33-2177 行。

总共提交了 13 个 commit,每步可单独回退。基础语法检查和其他校验它已经做好,人工检查了各项功能,全部正常运转。

这次重构非常成功,而且毫无波澜!

重构是要点脑子的,而且是一个非常严谨的问题,容不得半点错误。K3 能改完,没有错误,这一点还是略微出乎意料。2.8T 的参数,果然是稳了很多!

这一次测试结果还比较理想的。下一篇将要让它修改桌面软件的疑难 Bug 了,敬请期待!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›