实现一个随机文章按钮:从性能优化到交互仪式感的思考

我在我的笔记博客上做了一些更新, 其中包括对“随机播放”功能工作方式的调整。
于是我就想把这件事写成一篇博客。
“随机播放”?居然在博客里?
截至我撰写这篇文章时,我已经发布了974篇“笔记”。
为了好玩,我特意添加了一个“随机播放”按钮,可以随机从过往的笔记中抽取出一条。我时不时地按下这个按钮,就能重新邂逅一些来自过去的洞见。
这就像翻阅一本旧相册,随手抽出一张照片,然后心想:“哦,对了,我记得这个!真是美好的时光啊。”
就像那些老照片一样,偶尔也会有那么几张“没怎么耐看”的照片。
不过,我总觉得,随机挖掘出他人的旧日感悟,并从中不断获得灵感,是一件很有趣的事。
以前是怎么实现的呢?
由于我的网站是通过静态文件构建并托管的,没有运行时服务器,因此这一功能需要借助 JavaScript 来实现。
每一页都包含这样一段代码:
本质上就是:将每一个笔记 ID 注入到每一页的 HTML 中,当点击“随机播放”按钮时,系统会随机选取一个笔记 ID,并将用户引导至该笔记所在页面。
虽然不算多么优雅,但这个方案确实能正常运行。
问题在于,每当我发布一篇新文章时,所有页面都必须重新上传到 Netlify,因为每个文件的哈希值都会发生变化,其 ETag/缓存也会被失效。
这不仅让我的构建过程变得缓慢,也使得在开发阶段很难确保重构不会导致输出发生意外变化(参考 Dev.changes 由我的 SSG Web Origami 提供)。
于是,我决定做出一点改变。
那不使用 JavaScript 的方案又如何呢?
因为我一直喜欢看看自己能不能在没有 JavaScript 的情况下也能让事情顺利运转,于是萌生了一个想法:在构建时,通过我的 SSG 动态生成“href”,这样生成的输出就会像这样:
每次我重新构建网站时,只需让这段逻辑在静态站点生成器中运行,这样一来,每一页的 “href” 都会随着每次构建而有所不同。
优点: • 不需要 JavaScript • 不需要服务器(无需依赖请求时间的逻辑)
缺点: • 文件哈希值会在每次构建时发生变化(即使没有新增内容或模板变更,每一页的 HTML 页面都会因构建而拥有不同的 “href”)。这会导致部署速度变慢,因为 Netlify 必须在每次构建时重新部署每一个文件。此外,ETag 也会随之改变,因此缓存几乎失去了作用。
我最终决定不再采用这种方案,于是转而选择使用 JavaScript!
现在又是如何实现的呢?
我最初的想法是创建一个 JSON 文件,里面存储所有的笔记 ID。每当“随机播放”按钮被点击时,我就可以从文件中获取这些 ID,随机挑选一个 ID,再将用户引导至相应页面,例如:
这样就可行了。它将缓存问题集中到了一个文件中,因此在每次构建时,只需要失效或重新上传一个文件即可。
但在进一步尝试的过程中,我决定尝试一种稍微……不同寻常的做法。
我之前曾写过关于“大量小 HTML 页面”的故事——许多小小的 HTML 页面。当时我心想:“能不能把这项功能放在一个单独的 HTML 页面里,而不是放在 JSON 文件里呢?”
最终,我得到了这样一个链接,例如:
“随机播放”
当用户点击该链接时,系统会直接将用户导向一个新的页面。而这个页面内已经嵌入了所有的 JavaScript 逻辑,例如:
我对这种实现方式带来的体验有几个特别喜欢的地方。
首先:随机播放是一个路由,因此我可以直接跳转到该页面,而无需使用图形界面, 例如:notes.jim-nielsen.com/shuffle
其次:我会在 UI/UX 方面稍作延迟处理,让用户在点击按钮时,仿佛正在发生什么。 如果你点击按钮后立刻跳转到下一页、随机抽取的页面,那种感觉似乎来得过于迅速——仿佛你只来得及感受到“刚刚发生了什么? ”这样的瞬间。
然而,在这种场景下,系统会将你引导至“随机播放”页面; 你刚刚点击的按钮会变成一个旋转的进度条,并显示“正在处理中”的文字,随后在 JavaScript 执行并把你导向一条随机的笔记之前,会有一段短暂的(有意为之的)延迟。
我知道,这听起来有点奇怪。“引入人工的迟缓?你疯了吗?”但我很喜欢这种设计。它让人感觉,就像一台老旧的音乐播放器上的“随机播放”功能一样。
我记得,我曾经有一台 CD 播放器,配备了“随机播放”功能。每当我点击按钮时,小黑白色的屏幕上会显示“正在随机播放……”, 而你则会经历这样一段短暂的状态——我猜,硬件内部的读取头会沿着物理轨道移动, 直到找到新的、随机的歌曲,开始从 CD 上播放。
硬件的限制确实决定了这种体验的必要性,但我一直很喜欢它,因为它总让我觉得, CD 播放器仿佛在“思考”接下来要播放哪一曲。 这种状态清晰地向我传达了一个信息:我的“随机播放”意图已经被接收,并且正在被付诸实践。 我喜欢这种反馈,而这也正是我原本希望在笔记网站上实现的效果——尽管其实这完全没必要。
我喜欢那种短暂却清晰的反馈时刻:你的意图被准确接收,并且正在被付诸实践,而不是像快节奏的流程那样,让你甚至无法精确察觉到底发生了什么。
下面是一段视频,可以直观地展示这一过程:
为什么呢?
我知道,对于这么一个小的功能来说,这可能涉及太多信息——甚至可以说,有些多余。
不过,我依然乐于分享自己在为自己构建事物时所做出的决策过程。
所以,我才有了这篇帖子。
回复方式:
电子邮件 ·Mastodon ·