90年代复古博客

把 1998 年搬进 2026:一个 SQLite、一个 DOS 提示符、六个依赖

开源地址:github.com/xiwen-haochi/oldie-blog

前置声明:它有 bug,而且我清楚地知道是哪些。

一、起因

我逛了三个月的老式个人主页,发现一件事:它们比现在的博客快。

不是加载快几十毫秒的那种快。是你按回车,页面就在那里了。没有轮询,没有水合,没有一个 3 MB 的框架在后台偷偷跑。没有"加载中"。

于是我想做一个:界面停在 1998 年,行为停在今天。

现在它长这样:

在这里插入图片描述

二、它长什么样

文章列表

置顶的在最上面,新的在最下面。排序规则只有一条,写在一个地方,全站共用 ------ 我曾经把这条规则在三处各写了一遍,然后三处互相不同意。

文章页

Markdown 进,HTML 出。description 缺省取正文开头,中英文混排、全角标点、行内代码都正常,阅读时间按中文习惯算(一个字约等于两个拉丁字符宽)。

1998 模式

一键把整站换回藏青桌面 + 居中排版 + Times New Roman。

需要说明的是:它只是个 CSS 主题。它不会让浏览器变慢,不会把 HTTP 响应改回去,也不会停止计算它刚刚花 8ms 渲染出来的 HTML。别指望更多,也别担心更多。

后台

后台地址可以改,默认 /admin,从不出现在任何公开页面里,也不会被搜索引擎收录。

三、几个我自己比较喜欢的功能

① 每个页面都有一个 DOS 终端

按 Ctrl + K。

它不是录屏,也不是装饰。它执行的是真命令,打的是真数据:

dos 复制代码
C:\OLDIE>dir
C:\OLDIE>search 关键词
C:\OLDIE>stats
C:\OLDIE>snake
C:\OLDIE>neofetch

neofetch 那一栏的运行时依赖数,是从 package.json 里读的。你改一个依赖,输出就变 ------ 不会像很多"关于本站"页面那样,写死一行字然后过期三年。

还有 ping 是从你浏览器真实发一次请求 测出来的往返时间,不是 Math.random()。

② 终端里能打游戏

dos 复制代码
C:\OLDIE>snake
SNAKE  (c) 1991, one small computer
  arrow keys or WASD to steer · q quits

方向键或 WASD 控制,q 退出,最高分存 localStorage。整个游戏跑在你浏览器里,服务器全程不知道它存在。

③ 芯片音乐,0 字节

按 ♪ 按钮。那个 BGM 是 Web Audio 现场合成的方波。

音频资源大小:0 字节。 下载量 0。你按下去才开始有声音。

④ 留言簿

带审核队列,有蜜罐反垃圾。留言可以选择不公开地址 ------ 签名的人永远看不到自己的邮箱被谁拿走。

⑤ 全文搜索,懂中文

不是把中文塞进英文分词器里祈祷。

  • 中文按 unigram + bigram 建倒排索引,所以搜"后训练"能命中"大模型的后训练"
  • 支持 tag:前端 限定标签
  • 支持 "一个短语" 精确匹配
  • 支持 in:title 只搜标题

⑥ 其它

webring(带邻居)、访问计数器(总数/今日/独立访客/在线)、走马灯、闪烁文字、每篇文章都能下载 .TXT、中英切换。

朗读功能:正文里点「📻」,用系统自带的语音合成念给你听。一篇长文通勤路上听正好。

四、技术上我做了什么选择

全部数据在一个文件里

data/oldie.sqlite:

设置、文章、页面、留言、访问计数、订阅者、会话 ------ 全在里面。

用 Node 自带的 node:sqlite,不装任何数据库。

这里有个我踩过的坑,值得单独说:我最早是"每个 store 一个 JSON 文件"的架构,后来改成单一数据库。改完之后,示例站点里那句"存储:Markdown 文件 + 几个 JSON,没有数据库就没有迁移"就变成了假话,而且它就印在每个新克隆的人会看到的关于页面上。

教训:文档漂移比代码过时更难发现。代码过时会有测试报警,文档里的假话只会安静地骗人。

六个运行时依赖

复制代码
express  ejs  markdown-it  highlight.js  gray-matter  multer

其余全在 src/lib 里自己写:

需要的 换成
搜索库 支持中文的倒排索引
session 库 HMAC 签名 cookie
bcrypt node:crypto 的 scrypt
压缩库 手写 gzip 中间件
S3 SDK 基于 fetch 的 SigV4 签名
ZIP 库 自己写的 deflate/store 打包与解包
HTML 消毒库 白名单消毒器

没有编译器,没有 node-gyp,没有原生模块。 新克隆 pnpm install 几秒就完。

没有构建步骤

前端就一个 public/js/site.js,服务端渲染的 HTML 直接用。

NODE_ENV=production 下静态资源开长缓存,HTML 走 no-cache。就这样。

备份是一个 .zip

后台一键导出,包含数据库、上传的图片和配置。

恢复是先把旧文件挪到一边,不是删掉。 所以手滑了可以反悔 ------ 这是我唯一一个坚持不做"干净利落"的地方。

五、跑起来

bash 复制代码
git clone git@github.com:xiwen-haochi/oldie-blog.git
cd oldie-blog

nvm use            # 推荐 Node 24(.nvmrc 已经提交)
pnpm install
pnpm start         # → http://localhost:4173

第一次启动会在终端打印一个临时后台密码。想先看看长什么样:

bash 复制代码
pnpm seed          # 五篇示例文章、一个留言簿、一个计数器

六、部署

bash 复制代码
cp .env.example .env      # 填 ADMIN_PASSWORD 和 SITE_URL
docker compose up -d

推到 GitHub 会自动跑测试并构建镜像到 GitHub Container Registry。

Railway 上只需要三件事:

  1. 挂一个卷,路径填 /app/data。 Railway 的文件系统是临时的,不挂卷下次重新部署整站清空
  2. 设 ADMIN_PASSWORD、SESSION_SECRET、SITE_URL 三个环境变量
  3. 端口不用管,Railway 会注入 PORT

八、一句话总结

它不追求快过 LightCMS,也不追求功能全过 WordPress。

它只做一件事:让你按回车,页面就在那里了。

1998 年就是这么上网的。我觉得没什么丢人的。


如果你也想让 2026 年的自己用回 1998 年的方式写博客:

bash 复制代码
git clone git@github.com:xiwen-haochi/oldie-blog.git

MIT 许可,随便改,改坏了是你自己的博客。

相关推荐
波力海苔夹心脆6752 小时前
C# 值类型与引用类型详解:存储位置、赋值机制、参数传递、相等比较、装箱拆箱与常见陷阱
开发语言·jvm·经验分享·笔记·c#·.net
AOI小白新手上路4 小时前
从 Keil 调试视角看 51 指针,到 Cortex-M 内存映射访问寄存器 · 学习笔记
笔记·学习
坤坤子吖6 小时前
ELF加载、动态链接、GOT与PLT
linux·笔记·学习
hgfsjk6 小时前
野莓采集图片修改指南:从单张处理到批量优化
大数据·经验分享·笔记·其他
咖啡忍者7 小时前
【SAP BASIS】Section 11: SAP System Landscape
笔记
嵌入式DZC7 小时前
嵌入式开发笔记随记
笔记
懿路向前7 小时前
【唤醒实战笔记】2026-09-29 | 智能体提示词迭代史(v1 → v8)
linux·笔记·算法
2601_957883847 小时前
2026年9月:雷神专业维修服务保障
笔记
71-38 小时前
MySQL密码重置
数据库·笔记·学习·mysql