九千行代码,七千行样式:一份建站工程账
站是做出来的,不是想出来的。但这篇不谈审美,只算账——把所有能数清楚的东西数一遍。数字不会撒谎,它们会告诉你时间到底花在哪儿了。
一、总量
| 项目 | 数值 |
|---|---|
| 提交次数 | 225 |
| 自己写的代码 | 9,666 行(.ts / .tsx) |
| 其中 React 组件与页面 | 8,095 行 |
| 样式 | 7,232 行(单个 globals.css) |
| 第三方依赖 | 11 个 |
| 页面 | 17 个 page.tsx |
| 构建产物 | 23 个路由(含 sitemap、feed),写成此文后是 27 |
| 全量构建耗时 | 约 3.5 秒 |
第一眼能看出来的怪事在这里:样式行数已经接近代码行数的四分之三。
二、提交的分布
10-11 ██ 9
10-12 █ 1
10-13 ████ 15
10-14 ██████ 21
10-15 █████████ 35
10-16 ████████████ 44
10-17 ██████████████████████████ 97
10-18 █ 3
一共八天有记录。三分之一的提交集中在同一天,那天在重做照片墙和页脚。
这说明一件不太好听的事:前期我在"想",后期我在"改"。真正把东西做对的那部分工作,全堆在曲线的尾部。
三、为什么样式会变成七千行
因为它被当作施工日志在用。
一个文件里同时住着:设计变量(颜色、间距、毛玻璃参数)、基础排版、每个页面的私有布局、以及一百多处"覆盖某条规则"的补丁。
举例:.post-shell 这一段被改过十几遍,因为每加一个页面就要重新调它的内边距;.about-name 这个类在文件里出现了两次,第二次是覆盖第一次的。
坏处很明显:改一处要靠搜索确认没有副作用。好处也有:所有样式在一屏之内可查,不用在十几个模块之间跳来跳去。这是个权衡,不是我没想过拆。
四、体量最大的五个组件
| 文件 | 行数 | 干什么 |
|---|---|---|
LeafLayer.tsx |
1,228 | 竹叶、太极、毛笔字,一块 canvas 全包 |
GalleryGrid.tsx |
489 | 瀑布流、灯箱、缩放拖拽、视频卡 |
HeroParticles.tsx |
381 | 首屏星尘 |
MusicProvider.tsx |
360 | 播放状态、队列、跨页不断播 |
ArchiveExplorer.tsx |
342 | 归档的搜索、筛选、时间轴 |
排第一那个组件,占全部组件代码的 15%,干的却只是"背景里飘点东西"。氛围类的东西最容易失控:因为它没有明确的对错,只有"再飘一点会不会更好"。
五、依赖为什么只有十一个
next react react-dom
unified remark-parse remark-gfm remark-rehype rehype-stringify rehype-slug
@shikijs/rehype gray-matter
除了 Next 和 React 这一套,剩下全是把 Markdown 变成 HTML 的流水线:解析、扩展语法、转 HTML、给标题加锚点、给代码上色,最后一件事交给 gray-matter 读前言。
没有一个图标库——图标是手写的内联 SVG;没有一个动画库——动效是 CSS 关键帧;没有一个 UI 组件库——所有卡片都是自己写的 div。
这不是"极简主义",是算术:每多一个依赖,就多一个人可以在半夜改坏你的站,也多一份要跟着升级的东西。
六、静态导出的账
构建是 next build + output: "export",产物是一堆纯文件。这带来几笔很清楚的账:
赚的:
- 不需要服务器进程,也不怕它挂
- 全站没有一次数据库查询
- 页面是预渲染的 HTML,首屏不需要等 JS
付的:
- 没有服务端,就没有「实时」。所有内容改动都要重新构建
- 图片优化服务不可用,照片墙只能用原图(所以压缩必须在上传前做完)
- 预取的 RSC 请求在静态站上会拿到 404——无伤大雅,但控制台不太好看
最后这笔账我认了。一个不会生病的小屋,值得放弃一点实时性。
七、所以时间花在哪儿了
如果把 9,666 行和 7,232 行加起来,再除以九天,大概是每天两千行。这个数字毫无意义——因为删掉的行没被统计进去。
真实的时间分配更接近这样:
重新构想版式 ████████████████
调数值 ████████████
写新功能 ████████
修 bug ██████
写内容 ████
最多的时间花在"把已经能跑的东西推倒重来"上。
这也解释了为什么提交曲线那么抖:不是我在加速,是我在不断否定前面的自己。
