返回文章
NO.
009
DATE
READ
~5 min
STATUS
原文

TAGS: 笔记 项目 架构

我给求职期的自己造了一把时间尺:一个零依赖 PWA 的工程纪律

一个只做一件事的本地时间记录器——看清时间到底进了哪里。记录我如何用零依赖、无构建的原生 PWA、一套写进仓库的红线治理,以及 14 条根因复盘,逼自己别用打磨工具逃避真正该做的事。

草稿:本文由 AI 依据项目文档与提交历史起草,语气/细节留待作者本人校对后再发布。

你把时间花在哪里,就会成为什么样的人

求职期最难受的不是投简历,是晚上回想一天——好像很忙,但说不清忙了什么。到底有多少时间真的推进了面试,多少时间在「研究工具」「学方法论」「刷文章」里悄悄溜走?

我想要的不是又一个效率 App,不是习惯打卡,不是给别人看的仪表盘。我只想要一把尺子:每天量一下,时间到底进了哪里,然后诚实面对。

于是有了「时间尺」。它只有一个用途,也刻意只保留这一个用途。

时间怎么被存下来:点,而不是区间

大多数计时工具存「区间」:一条记录带开始和结束。听起来自然,但一旦要补录、要切分、要跨午夜,区间之间的重叠和空隙会变成无穷无尽的边界 bug。

时间尺存的是:每条记录只有一个开始时间戳,它的时长 = 到下一条记录的间隔,渲染时实时算,不存储。今天最后一条没有右邻,就结算到「现在」;历史某天没有右邻,就结算到当天 24:00。整个模型只有一个硬边界——本地自然日的 00:00。

这个选择让「补录一段过去的时间」变成一次有界插入:给一个起点和终点,把这段切出来贴上新标签,段尾自动补回原来的标签,其它段一动不动。所有写路径——新增、编辑、删除、补录——最后都收敛到同一个归一化出口:去掉冗余的相邻边界,并且永远给今天留一个尾部占位。删除也不再「静默把这段并进前一段」,而是要么两侧同标签自动愈合,要么老老实实转成「未记录」。

一个记录器最容易骗自己的地方,就是把「没记」渲染成某种确定的东西。时间尺宁可显示灰色的「未记录」,也不替你脑补。

工程上,它是一个「反潮流」的 PWA

没有框架,没有构建步骤,没有打包器,没有 npm 运行时依赖。就是 index.html + 一个 styles.css + 一组原生 ES modules,浏览器直接 type="module" 加载,GitHub Pages 从仓库根目录直接发布。

这不是复古情结,是为纪律服务的约束

  • 零依赖意味着没有供应链,没有「升级 47 个包」的周末,没有构建产物需要解释。
  • 无后端、无账号、无云同步意味着数据只在你自己的 localStorage 里,代码和界面可以完全公开,而记录永远不出本机。
  • 模块边界被写死进文档:时间工具不碰 DOM,统计逻辑不碰 navigator,UI 层不做持久化。每个文件只干一件事。

整个 App 加起来大约 195 KB(gzip 后 ~73 KB)。我在路线图里认真算过一次内存和体积,结论是:目前没有性能问题可解,主动优化就是典型的镀金。把这句话写下来,是为了以后想「优化」的时候能被自己拦住。

真正的产品,是那套红线

代码只有几千行,但仓库里最重要的文件不是代码,是 CLAUDE.md——一份写给未来的我(和任何 AI 协作者)的维护红线:

  • 无运行时依赖 / 无构建 / 原生 ES modules 是铁律,npm 只允许作为开发期测试依赖。
  • 改了任何运行时资产,必须同步 Service Worker 缓存列表、manifest 版本、审计脚本里的期望版本号——一次版本仪式,四处对齐。
  • 提交前必须跑四件事:红线审计脚本、确认逻辑 smoke(用真实 node 导入真实模块跑)、Playwright 响应式 UI smoke、git diff --check
  • 一条数据一致性铁律:任何「先查后存」必须共用同一次 load 的结果,禁止改一张对象图、存另一张。这条是用血换来的(见下文)。

还有一条元规则,直白得有点扎心:

最大风险 = 用打磨这个工具来逃避面试推进。 每次「再加个功能」冒出来,先问:今天目标公司的约面推进了吗?

我甚至给它上了个硬门闩——28 天真实记录之前,不做可扩展分类法、不做报表、不做云同步。数据还没攒够,功能就是镀金。这个规则会主动提醒我,包括提醒帮我写代码的 AI,在求职没实质进展时别陪我一起逃避。

14 条复盘,都是根因不是补丁

项目有一份 postmortems.md,到现在 14 条。每一条都要求写清现象、根因、修法、护栏——不允许「改一下试试」。举两个印象最深的:

编辑功能「看起来没实现」。 用户反馈改了记录不生效。根因是 commitEdit 里 load 了两次:在 A 图上改,把没改过的 B 图存了回去。表面像「功能没写」,其实是数据一致性事故。修法是单次 load、在被保存的那张图里取记录,并把这条上升成红线。

iPhone 上保存后「抖一下」。 编辑长记录、保存时界面会二次重排。根因是同步关闭表单时,iOS 的软键盘还在,收起键盘后视口晚一帧才 reflow,于是肉眼可见地跳了一下。修法是:检测到键盘在场时,先 blur,等 visualViewport 稳定,再在单帧里关闭+重渲,并加一个过渡护栏遮住残余重排;桌面和 headless 保持原来的同步路径,好让自动化测试不 flake。| ps: 实测仍未解决,暂不推进,求职结束之后再继续打磨。

写复盘的价值不在于记录 bug,在于逼自己找到那一层「为什么」,然后把护栏加进测试,让同一个坑不踩第二次。(顺便:min-width:0 那个 grid 撑爆的坑,这仓库踩了两次,第二次我终于把它写进了记忆。)

AI 协作的一个旁注

这个项目大量用 AI 结对来写。有意思的经验是:AI 会热情地陪你镀金。你说「再打磨一下滚轮手感」,它不会拦你。所以我把「别镀金」「28 天门闩」「最大风险是逃避面试」直接写进给 AI 的指令文件里,让约束成为上下文的一部分——纪律不能只靠人自觉,得写进系统。

另一条踩过的坑:多步改动必须走主线程、串行做。想并发 fan-out 子任务提速,结果上游 API 扛不住并发,直接 429。于是「串行、逐个做」也进了红线。

它现在是什么

一把尺子,不是一个产品。零依赖、可离线、数据不出本机、代码完全公开(AGPL-3.0)。它帮我做的唯一一件事,是每天诚实地告诉我:时间进了哪里。

如果你也在求职期,或者只是想知道自己的时间都去了哪,也许你不需要又一个功能繁多的 App,只需要一把够诚实的尺子。

评论 →

CC BY-NC-SA 4.0

本文采用 CC BY-NC-SA 4.0 进行许可。

参考链接

  • 时间尺体验入口 随时随地记录自己,数据保存在本地,支持导入、导出、生成markdown摘要(可喂给AI分析),欢迎体验。

评论

评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion