现在打开这个站,你会看到一片会动的苍山洱海、一篇篇文章,还有几款能直接试玩的游戏。很多人以为这种站点背后有一套复杂系统,其实它就是一堆 HTML、CSS 和 JavaScript 文件:页面没有采用应用框架;现在发布前会在本地打包公共资源并更新缓存,再把静态文件交给 GitHub Pages。这篇把整个站拆开讲一遍,也记录一下最近的一些折腾。

整体长什么样

站点根目录下的文件就是全部源码,主要入口这么几个:

文件 / 目录作用
index.html首页:博客、动态、关于都在这一页
about.html个人空间(里面还藏了两个小游戏,后面说)
tools.html / games.html工具与游戏的作品展示页
posts/文章目录,每篇博客一个 HTML 文件
css/ js/ assets/样式、脚本和图片音乐等素材

各个页面共用同一套样式和脚本,文章的正文则独立成页、互不依赖。想加一个新页面,复制一个模板改改内容就行,成本很低。

博客系统:一篇文章就是一个文件

每篇文章放在 posts/ 下,是一份完整的 HTML。主页的「最新文章」卡片并不在页面里写死,而是由 js/app.js 里的一份文章列表驱动的:每一条包含标题、分类(学习 / 生活)、摘要、日期和文章链接,脚本加载后按日期排序、渲染成卡片。

这个设计带来两个顺手的功能:

  • 搜索和筛选在本地完成:主页的搜索框和「全部 / 学习 / 生活」筛选按钮,全部在浏览器里对这份列表做匹配,不请求任何服务器接口;
  • 没有脚本也能看:页面里保留了同样的静态卡片作为兜底,万一脚本加载失败,文章入口依然都在,只是少了搜索和筛选。

所以新增一篇文章要做三件事:写一个文章页面、在脚本的文章列表里加一条、在首页补一张静态卡片。文章修改后还需要刷新全文搜索索引,打包公共资源并更新缓存版本,再完成本地验证。

这也是为什么这个站几乎不会「挂」:内容全部是静态文件,服务器只负责把文件发给浏览器,剩下的都在浏览器本地运行。

山水背景:一个会动的封面

首页顶部是一幅「苍山 · 洱海」,用 Canvas 画出来的:湖面有沿透视扩散的波纹,点水或拖动会漾开水波,带动倒影和水光;点一下山,山间的云雾会随风移动,山体保持稳定。右下角还有一排风景控制按钮,可以只看背景、暂停动画,或者打开设置面板。

设置面板里是五个滑块——湖面起伏、风的速度、山间云雾、水面微光、渔灯密度,外加一个「切换夜色」。夜色模式下渔灯会亮起来,湖面泛起细碎微光。

最近一次比较大的折腾,是手机端的性能优化。原来的背景图晨光约 310KB,而且动画在任何设备上都按同一规格跑,手机容易卡。现在的做法:

  • 背景图换成 WebP 压缩版,晨光从 310KB 降到约 88KB;
  • 手机的水波网格降到 128 × 96(原来的四分之一),帧率上限 24fps,每帧渲染像素上限约 42 万;
  • 页面先显示静态背景,动画等首屏画完再启动;滚动离开首屏或切到后台就停止,回来再恢复。

本地模拟的手机端数据(390×844 屏幕、3 倍像素密度、1.6Mbps 网速下):背景下载完成约从 2.5 秒降到 1.5 秒,动画首帧约从 2.9 秒降到 2.2 秒。数据来自本地模拟,不代表所有手机的实测结果,但方向是对的——手机先看到图,动画随后再来。

给网站配点声音

导航栏右侧有个音符按钮,点开是音乐播放器,里面放了 11 首歌。播放后列表收起,变成一个可以拖动的小窗:上一首、下一首、暂停、拖动进度条,随时停止。

藏在关于页里的小游戏

个人空间里藏了两个彩蛋,不看提示基本发现不了:

  • 「ABOUT ME」前面的细红横线,点一下会打开一个五乘五的贪吃蛇;
  • 标题「ChenC.」末尾的红色句点,点开是俄罗斯方块。

两个小游戏都有得分和最佳记录,支持暂停、重新开始,键盘和屏幕上的按钮都能操作。它们的存在让「关于我」这页多了点意外,也算是我最喜欢的部分之一。

游戏和工具有了自己的作品页

最近把做过的作品整理成了两个展示页,左右滑动浏览,每个作品都配了不同的动态场景背景:

  • 当前游戏(6 款):一念天下(历史卡牌策略试玩版)、羽境 · 火柴人羽毛球、海绵宝宝大战僵尸鱼(同人小游戏)、海底塔防(独立在线项目)、节拍失控!BEAT.exe、DOG WALK;
  • 工具(2 款):多书知识问答台(6 本教材 326 条知识点,语义检索 + 引用溯源)、Note to Site(Obsidian 插件,把笔记转成文章 HTML 和彩色思维导图)。

其中多书问答台和空课查询系统之前都写过开发记录,可以顺着博客列表往回翻。

当前发布流程:GitHub Pages

修改源文件 → 更新文章全文搜索索引 → 本地打包公共资源与缓存版本 → 验证页面、入口与手机布局 → 更新发布记录 → 由站长提交并推送 GitHub → 等待 Pages 发布并核验线上内容。

网站不需要在发布服务器运行应用框架;资源打包在本地完成。独立的在线 AI 与判题服务另行运行,不能把它们等同于静态页面本身。

早期发布方案:Netlify 增量直传(已停用)

早期源码放在 GitHub,主站当时托管在 Netlify,域名 chenc.com.cn 通过 CNAME 记录指向站点。部署用的是增量直传的方式:一个脚本负责对比并上传有变化的文件,不重传整个站。每次更新前设置站点目录、站点 ID 和部署凭据,运行脚本后等发布状态变成 ready,再打开线上页面确认一遍。

另外有一条自己定的规矩:每次更新网站,都要在更新记录里登记——改了什么、部署了没有、部署结果如何。这样几个月后回头看,每个改动都有据可查。

静态站的好处就一个字:省。主站页面由静态托管提供,不需要运行应用服务器或数据库;现在使用本地资源打包,结构仍然便于维护。缺点也有,比如没有后台,发文章要靠改文件,但对一个人维护的小站来说,这反而是最稳的方式。

接下来打算继续写博客,把文章写成这个站最核心的内容;工具和游戏也会接着打磨。网站是一点一点长出来的,这篇记录的只是它目前的样子。