— Blog · 笔记

我们为什么把主页上的 React 和 Babel 去掉了

Why a one-page studio site was shipping 4.2 MB of JavaScript, and what it ships now.

TL;DR · English

On 2026-09-05 we replaced the React + Babel-standalone setup behind oddduck.ooo with plain HTML. The old page downloaded 4,226 KB of JavaScript — Babel 3,064 KB, React DOM 1,055 KB, React 107 KB — and compiled its JSX in the browser before painting anything; on a wired line that alone took 512 ms. The new page ships about 11 KB of vanilla JS and paints in under 100 ms on a local server. Nothing visible changed.

从 2026 年 9 月 5 日起,oddduck.ooo 的主页不再用 React,直接以静态 HTML 提供。在那之前,第一个像素出现之前要先下载 4,226 KB 的 JavaScript,还要在浏览器里编译 JSX。现在是 11 KB。

起因是一句话:“打开网站好像太慢了。”我们先怀疑服务器,结果服务器没问题。问题出在我们做主页的方式上。

到底是什么慢

事实 改版之前,主页的 HTML 正文几乎是空的。画面要等三个脚本从外部 CDN 到齐,才由 React 画出来。生成画面的代码没有预先编译,所以每个访客的浏览器每次都得自己编译一遍(截至 2026 年 9 月 5 日)。

事实 2026 年 9 月 5 日,我们在有线网络上关掉浏览器缓存,把这三个文件重新下载了一遍。结果如下。

文件大小下载
@babel/standalone 7.29.03,064 KB290 ms
react-dom 18.3.1 (development)1,055 KB146 ms
react 18.3.1 (development)107 KB76 ms
合计4,226 KB512 ms

三件事叠在了一起。第一,我们用的是开发版构建。换成生产版,两个 React 文件会从 1,162 KB 降到 140 KB 出头。第二,3 MB 的 Babel 完全是为了在浏览器里编译 JSX 才付的代价。第三,正文是空的,所以要等这些全部到齐、编译完成,第一个像素才画得出来。在那之前,访客看到的是一片米色空白。

在有线网络上,光下载就要 0.5 秒。换成带宽只有五分之一的线路,简单算下来是 2.5 秒。再往上还要加解析 3 MB 脚本和编译 JSX 的时间,这部分由访客设备的 CPU 来扛。这个结构,和“太慢了”的感受正好对得上。

顺带一提,服务器不是问题。事实 同一天我们自己测,服务器的首字节响应是 100~270 ms,所有图片加起来也只有 270 KB。

当初为什么这么做

这个站点一开始是个设计原型。为了一边改字体和文案一边看效果,我们在画面角落挂了一个调节面板(tweaks panel)。想快点做出来,就用了 React,JSX 也干脆放在浏览器里编译。“不设构建步骤”的原则碰上“想马上看到”的心情,做出来的就是这样的结构。原型没改,直接上了线。

事实 那个调节面板从来没有对访客渲染过一次。可它那 25.8 KB 的代码,每次访问都跟着一起编译。

换成了什么

主页是个单页介绍站。能算作状态的,只有移动端菜单开没开。所以我们没换框架,而是把框架去掉了。

  • 原来由 React 生成的画面,直接写进了 HTML。浏览器一收到就画。
  • 菜单、移动端抽屉,还有点鸭子时的那声嘎,都挪进了一个小脚本。
  • 状态栏和键盘快捷键留在原来那个小脚本里,没动。
  • 字体改成在文档头部直接取,不再从样式表里一个接一个地拉。以前要等样式表全部到齐,字体才开始按顺序下载。
  • 调节面板和那些需要编译的文件,删了。

构建工具还是没有。改完文件传上去,上线的就是它。我们想守住的是“不构建”,不是“React”。

结果

事实 改版之后,在本地服务器上(字体已缓存):First Contentful Paint 96 ms,DOMContentLoaded 53 ms。线上首次访问的 DOMContentLoaded 是 361 ms。主页一共加载两个脚本,合计约 11 KB(2026 年 9 月 5 日测量)。

之前之后
JavaScript4,226 KB + 49 KB 的 JSX11 KB
浏览器内编译每次访问无
到第一个像素全部到齐并编译之后HTML 一到就画
构建步骤无无

看得见的东西一点没变。颜色、字体、鸭子、嘎声、跑马灯、移动端抽屉,全都一样。变的只是它们到达画面所走的那条路。

我们学到的

把原型阶段的做法留在线上,代价是访客来付。尤其要说清楚:“不构建”不等于“不打包”。在浏览器里编译并不是省掉了构建,而是让每一个访客各构建一次。

所以我们的原则里多了一行:不要再把 React 放回来。哪天画面有理由大改,我们会再想一想;但为了一个介绍页挂上 4 MB 的编译器,这样的理由大概不会有。