上一篇文章提到,26 年 10 月发生了一场大规模 js 投毒事件,本站的一篇文章也被植入了恶意代码。在 AI 时代,挖漏洞如同喝水一样简单,而我们个人网站无法做到及时响应每一个漏洞,所以全站静态化就成了最好的出路。当然,静态站的好处也不只是安全:
- 静态站可以托管到 Cloudflare Pages、Github Pages、腾讯云 EdgeOne。它们免费且低延迟,能省下一大笔成本。本站此前部署在阿里云上,最初是按流量计费,后来账单日益高昂,改用 200Mbps 峰值带宽、不限流量的轻量应用服务器。这种轻量应用服务器,4GB 内存的实例要 714 CNY 一年(2GB 则是 459 CNY/年,但不足以运行 Ghost),且国外访问的延迟较高。迁移到 EdgeOne 之后,不仅免除了服务器费用,用户访问体验还有所提升。不过需要注意,免费托管服务一般对仓库大小、单个文件大小都有限制,常见的限制是全站 5GB、单个文件 25MB。
- 静态站更容易定制。在 AI 的帮助下,博主想要什么功能就可以有什么功能,不用担心与主线版本不兼容。对于本站来说,迁移到 Astro 之后,顺手就解决了几个 Ghost 的陈年问题:Ghost 后台对中文输入法很不友好;图片粘贴上传功能有 bug,每次粘贴图片之后图片必定立即消失,要按 Ctrl+Z 以复原;以及一个性能缺陷(存在多个并发用户的时候,页面加载非常慢)。
💡
笔者强烈建议所有动态博客站迁移到静态方案。对于确有动态程序需求的博客站,也建议配置反代策略以提升安全性。例如,对于 Ghost,可以默认禁止访问
/ghost/ 路径,仅允许 VPN 或白名单 IP 访问。笔者通过 Opus 5.5 / Claude Code 完成了初步迁移。先把 Ghost 博客的数据和 docker compose 文件打包,然后让 Opus 将其本地运行起来、再编写 Astro 代码复刻之。提示词如下:
拟将本博客网站重构为 astro 静态站,以后用 markdown 写文。核心要求:
- 恢复所有公开文章。草稿状态的文章则全部忽略
- 尽量复刻现有的 ui,尽量不让用户察觉到差异。首页要保持渐进加载,不要一次性载入所有文字和图片。如果你认为有些东西复刻起来比较困难,通知我
- rss功能、评论功能要能继续运作
- 顺便修一个陈年老问题:有些博客是用css实现的段首空格,有些是直接插全角空格。以后统一为css段首空格
- seo水平不能降低
你可以用 mise 管理依赖。先拟一个迁移方案。
Claude 分析了一通之后,拟的方案是:
- 迁移 146 篇已公开的文章、1 个 page(也就是
/about),忽略 14 篇草稿 - 维持各篇文章的
location.pathname,让 Gitalk 能正常找到对应的 Github issue 评论区 - 首页初次加载 25 篇文章,然后每次抓取
/page/N/并把 dom 添加到页面中(这也是 Ghost 原本的实现方式) - 使用源站的
screen.css、casper.js等文件;重写页面模板,把 Ghost 中的每个.hbs重写为 Astro 组件,使之生成一模一样的 dom - 源站的文章是 html 格式,需要写一个迁移代码把它转成 markdown
- Ghost 会计算每篇文章阅读时间、用
31 Oct 2026格式展示日期,需要重新实现这些行为 - 关于 SEO,继续提供 head 标签(例如
canonical、og:description等);生成 sitemap、rss。不再提供 AMP,而是将/slug/amp/直接 301 到/slug/ - 验收时,比较 html 生成是否一致、用 playwright 截图比较实际渲染是否一致
笔者的评审意见是:可以抄源站的前端文件,但是要裁剪掉不需要的代码,以最小化体积;amp 功能直接放弃,因为托管到静态站之后很难精细地设置 301 跳转(一般都有规则数目限制)。接下来就是让 Claude 放手去做,最终新站与旧站的渲染结果逐像素一致。
完成复刻之后,笔者切换到 GPT-6.1-sol 做了一些优化。包括:
- 把首页图片自动裁剪成 720 × 450 像素,并转为 webp,从而缩小体积
- Ghost 的视频播放器比较复杂,要设置宽度、高度、缩略图。旧文章的视频维持原样,新文章则采用浏览器原生播放器
- 笔者以前嫌 Ghost 的 h2 太大,经常使用 h3 或 h4 作为章节标题。这次重新指定各级 header 的尺寸,并把所有文章改成使用
##作章节标题 - 为 Gitalk 添加暗色模式支持
- 代码渲染从 highlight.js 迁移到 Shiki,构建时就完成渲染,从而读者浏览器不再会出现“最开始没高亮、半秒之后有高亮”的情况
现在,本站已经接近笔者理想中的状态。但愿读者们得到了更好的阅读体验。
