Vibe Coding 实践:如何打造纯浏览器 DOCX 渲染组件

blackocean 2026-09-22 15:54 1

背景


我在做文档翻译网站 O.Translator (国外版) 和 商译 AI (国内版) 的时候,需要在浏览器支持 DOCX 、PDF 、PPTX 等不同文件的渲染预览。


项目初期,大部分文件类型预览都是使用开源库,对于 DOCX 文档,我选择了 VolodymyrBaydalka/docxjs


这个库做基本展示没问题,但大文件渲染( 20M 以上),会卡,有时候甚至让浏览器崩溃。初期,我只能在外层加门禁限制,比如 XML 超出 500 个或者文件超过 20M ,就不在网页渲染预览,让用户下载。


性能是最大的问题,直接导致很多 DOCX 文档没法在翻译完第一时间展示给用户,这个体验让我不太满意。其次,对于 XML 对象解析和 Style 族渲染支持度不够。


所以,早在一年前,我就有重写 DOCX 渲染库的想法,大体思路,整个架构基于 Worker-first 解耦,将耗时操作放到 Web Worker 中,比如解析、布局计算等,主线程只负责消费计算结果。
这样做,除了优化性能,还有一个考虑,引擎端输出结构化的布局语义,渲染端可以用 DOM ,可以用 Canvas ,甚至可以移植到小程序和 App ,这些长远规划在架构上要支持。


这个项目复杂度高,如果手动实现,难度很大。
我想过基于 VolodymyrBaydalka/docxjs 来重构,但它的架构和我的设想差别较大,也放弃了。


25 年尾声,我开始在主站小范围使用 AI 编程,从半信半疑写一些工具函数,到功能模块重构,我对 AI 的 coding 能力认可度不断提高。26 年 3 月,GPT-5.4 发布,我感觉是时候动手了。
我使用的主力模型是 GPT-5.4 和之后的更新版本。




开始动手


26 年 4 月开始动手。


初始架构


按我之前的想法,给 AI 设计了基于 Worker-first 布局的架构准则,有几个主要模块:解析、布局计算、渲染。



  • Worker 负责解析、测量、分页和页面数据;

  • Viewer 负责请求页面;

  • Renderer 只消费页面模型及资源包;

  • 缺能力时应扩展 Worker 输出,不能偷偷退回旧 DOM 路径。


这是第一次也是最基本的一次架构定义:从“HTML 渲染器附带分页”变成“布局引擎产生页面,DOM 只是一个渲染消费端”。


这个阶段,我能做的不多,大部分时间是在跟进度,以及审查 AI 划分的能力抽象和代码模块。这时的主力模型应该是 GPT-5.4 ,有时候会偏离架构设计规则。




第一次大规模测试


5 月中旬,整体架构编码完成,开始测试。


我设计了自动化测试 Skills ,这套 Skills 主要工作是用渲染引擎和 Word 打开同一个 DOCX 文档,对每一页截图做“相似度计算”(通过 Python 脚本),如果某一页的相似度较低,就提交人工审核,我会对比所有得分低的页面,评估修复优先级。


这个阶段,主要是用真实 DOCX 文档来测试解析引擎的稳定性,以及 XML 标签识别的覆盖面。
测试一段时间,大部分问题集中在分页计算,引擎内部混杂了:



  • twips 、pt 、px 、CSS 字符串;

  • 浏览器测量结果;

  • 针对某一页、某一种表格的分页阈值和补丁;

  • 表格、段落、图片各自维护部分几何判断。




重构:核心是分页计算


5 月下旬,我重构了分页单位计算,引入:



  • canonical layout units ;

  • Word 行盒;

  • 明确的段落、表格行和续页模型;

  • 页面模型中的几何与来源信息。


6 月又逐步把表格文本、对象、sourceRef 、合并单元格、图片和段落语义从巨型分页函数中拆到各自模块。
Renderer 不再通过 getBoundingClientRect、CSS reflow 或 tab 二次排版修正分页。


这次重构的本质是:把“浏览器看起来差不多”升级成“引擎内部有稳定、可验证的 Word 几何语义”。
不能出现“场景化实现和补丁”。


很快,我又遇到了新问题:修复一个问题,会导致新的问题出现,或者会让已经修复的问题再次出现。
同时,这样的测试和修复持续一段时间后,包体积在不正常的增大。
排查发现,是因为 AI 做了很多场景化补丁修复,我意识到,虽然整个骨架没问题,但里面的填充物不对。




再次重构:单一分页内核


7 月中下旬的这次重构,主要还是围绕分页器,但重点转移到,从分散分页器改成单一分页内核与渐进式 sealed pages 。


因为我发现,即使单位统一了,段落、表格、浮动对象仍可能分别决定:



  • 当前页是否放得下;

  • 是否换列或换页;

  • 是否拆分;

  • 如何记录 overflow ;

  • 是否重新计算前缀内容。


于是出现了“多个分页权威”,很容易导致边界漂移。
形成“多条决策路径”,在复杂系统中,可能是 AI 最常出现的问题。




第三次重构:对象驱动的核心模块


经过前几轮重构,基础框架已经完成,但代码里仍有历史包袱:



  • 根据正文内容、页码、短尾等特征做场景判断;

  • 表格和图形存在自己的隐式分页路径;

  • 页眉页脚、批注、资源可能在 Renderer 侧重新构建;


这个阶段,我开始明确设计针对 XML 标签解析的对象库,后面延伸到 Style 规则族等。
在 skill 中明确规定 Owner 单一主责、禁止多重决策。


最终形成的生产主链是:



OOXML/资源解析 → 类型化语义 → 流对象及候选 → 单一分页内核 → committed/sealed page → Renderer 绘制



现在基于对象驱动的解析引擎,我认为是一个合理的设计。这个架构,给了 AI 一份高效的蓝图,避免生成多重决策,避免之前出现的各个模块各自为战问题。
解释上面这句话,把标签、规则等等进行对象化之后,让 AI 修复一个问题,一定先落到一个对象 Owner 上,可能是 XML 标签对象,可能是 Style 对象,之后的修复都会在这个对象内部,不断发现问题不断改,只会让这个对象更“准确”。




发布第一版


9 月底,发布了第一版到生产。


基本达成我的初始构想:



  • Worker-first:文档解析过程,不会造成页面卡顿;

  • 渐进解析渲染:即使很大的 document.xml 文档,打开速度也很快;

  • 布局引擎与渲染解耦:未来可拓展;

  • 基于对象库的设计:后期持续优化、更新对象规则,会简单清晰很多。




实际应用效果


以下是两个翻译预览的 Demo ,其中 DOCX 文档预览就是用的这一套渲染引擎。



  • O.Translator - DOCX 文档翻译预览(国外版)

  • 商译 AI - DOCX 文档翻译预览(国内版)




To be continued


这个项目比我预期多用 2 个月完成。我对 AI 的能力,从 GPT-5.4 到 GPT-6.0 ,有了非常具体的感知。项目后期进度很快,一是因为架构是逐渐清晰稳定的,二是得益于 AI“更聪明”。


最大的感受,AI 是一把锋利的手术刀,要给它指出在哪下刀,如何下刀。当然,AI 可以帮助你找到下刀位置,但重要的是,你得知道。

最新回复 (2)
  • shuang 09-23 08:52
    1
    有 github 地址吗
  • blackocean 楼主 09-23 11:15
    2
    @shuang 还需要整理,开源再发出来。因为精力不太够用,在构思其他文档类型的纯前端渲染。其实,用我第三次重构的思路让 AI 做就可以,这个思路我认为是比较好的。
* 帖子来源V2EX
返回