再见了,WordPress,我把网站迁移到了 EmDash

宝哥发布于 约 8 分钟读完
再见了,WordPress,我把网站迁移到了 EmDash
目录6 节
  1. 一、WordPress 的问题,不在 WordPress 本身
  2. 二、为什么选 EmDash
  3. 三、清晰对比:搬家前 vs 搬家后
  4. 四、搬家是怎么做的
  5. 五、搬完之后,也有代价
  6. 六、写在最后

先说结论:如果你是个人站长,WordPress 和其他服务挤在同一台小服务器上,又没有精力天天打补丁,那么把网站搬到 EmDash 这类无服务器的 CMS,是一笔很划算的买卖。我刚搬完,下面是完整的复盘。

9 月 27 日早上 7 点,新加坡那台服务器的 CPU 突然被打满。

我登上去一看,一个来自印尼的 IP 正在用 Acunetix(AWVS)漏洞扫描器,以每分钟 300 到 400 次请求的速度,一页一页地"体检"我的 WordPress。它没有攻进来,但也不需要攻进来。这台 2 核 2G 的突发型实例用的是 AWS 的 CPU 积分制度:基准性能只有 20%,超出的部分靠积分撑着,积分一旦用完,CPU 就被限流在 20%。六个小时后,积分烧光了,整台机器彻底卡死,任何任务都运行不了。我在 AWS 后台看到 CPU 一直停在 20%,宝塔面板里的 CPU 则一直是 100%。

更要命的是,这台机器上不止跑着博客。网盘、iClone 的安装包下载站、抖音截流工具的后端、直播推流,全挤在同一个宝塔面板、同一个 nginx 里。一个扫描器冲着 WordPress 来,结果所有服务陪着一起瘫。

这不是第一次。Cloudflare 防火墙里那条"屏蔽 IP"规则,在这之前已经攒了 8 个 IP,每一个背后都是一次类似的扫描或攻击。

那天我把火灭了:在 nginx 里补上真实 IP 识别、封掉扫描器、加了页面缓存和按 IP 限速,机器总算缓了过来。然后我做了一个决定:

别再修了,搬家。

第二天,baoge.vip 从 WordPress 迁移到了 EmDash,跑在 Cloudflare 上。这篇文章讲讲为什么、怎么搬、搬完之后有什么不一样。

一、WordPress 的问题,不在 WordPress 本身

先说句公道话:WordPress 没有错。按 W3Techs 的统计,全世界 40.2% 的网站在用它,子比主题也陪了我好几年。问题出在"一个人维护的小站 + 一台共享的小服务器"这个组合上。

事后复盘,那次瘫痪暴露了几个长期存在的隐患:

1. 每一次访问都在跑 PHP。
服务器是 nginx,但装的是 LiteSpeed Cache 插件。LiteSpeed 的页面缓存只在 LiteSpeed 服务器上生效,在 nginx 上等于没装。源站返回 no-store,Cloudflare 也就老老实实地不缓存。结果是:每个访客、每个爬虫、每个扫描器的每一次请求,都要完整执行一遍 PHP + MySQL。扫描器每分钟几百次请求,就是几百次完整的页面渲染。

2. 攻击面太大。
xmlrpc.php、wp-login.php、wp-json、主题和插件里每一个 PHP 文件,都是扫描器的目标。我用的 PHP 7.4 早在 2022 年 11 月 28 日就停止支持了,子比主题停在 8.6,插件要一个一个跟着升级。Cloudflare 在介绍 EmDash 时引用了 Patchstack 的数据:WordPress 网站 96% 的安全问题来自插件。WordPress 创始人对这个说法和对比方式公开表示过异议,但对我这种装了一堆插件的小站来说,方向是对的:安全这件事,靠的是你永远不忘记更新。

3. 一个服务出事,所有服务陪葬。
博客、网盘、下载站、直播、业务后端共用 CPU、内存、磁盘和 nginx。扫描那天我还顺手发现:磁盘已经用到 88%,光 baoge.vip 的访问日志就有 3.7G。

4. 看不见攻击者。
nginx 没配 Cloudflare 的真实 IP,日志里全是 Cloudflare 节点的地址。想知道是谁在打,得去抓 php-fpm 进程的参数。

这些问题每一个都能修,而且我那天也确实修了。但修完我意识到:我在给一个本来就不适合的架构打补丁。

二、为什么选 EmDash

没有服务器

EmDash 是 Cloudflare 开源的内容管理系统,官方的说法是 WordPress 的"精神继任者"。就在我搬家的同一天,9 月 28 日,它发布了 1.0 稳定版。

它吸引我的地方有三个:

  • 没有服务器。 基于 Astro,用 TypeScript 写成,直接跑在 Cloudflare Workers 上。数据库是 D1,图片存在 R2。没有 PHP,没有 MySQL,没有宝塔,没有需要我半夜 SSH 上去的机器。
  • 插件在沙箱里跑。 WordPress 的插件和站点同权限运行,一个插件出了漏洞,整个站都暴露。EmDash 的插件运行在隔离环境里,只能访问自己的私有存储,碰不到站点内容、用户、密钥和网络;需要额外能力时必须先声明,再由管理员批准。
  • 没有密码可以爆破。 EmDash 默认用通行密钥(Passkey)登录,没有可泄露的密码,也就没有暴力破解的入口。
  • 后台还是后台。 我不想换成"改个错字也要 git push"的纯静态站。EmDash 有完整的可视化中文后台,写文章、改首页、调颜色、换菜单都在网页里完成,这点和 WordPress 的体验很接近。

三、清晰对比:搬家前 vs 搬家后

搬家前

对比项

以前:WordPress + 子比主题

现在:Astro + EmDash

运行环境

新加坡 2 核 2G 突发型实例,宝塔面板

Cloudflare Workers,全球边缘节点

技术栈

PHP 7.4(已停止维护)+ MySQL

TypeScript + D1 数据库 + R2 存储

页面缓存

实际没生效,每次访问都跑 PHP

边缘缓存,页面和图片由 Cloudflare 直接返回

被扫描时

CPU 打满、积分耗尽、整机卡死

请求落在边缘,没有一台"我的服务器"可以被打满

故障影响范围

博客、网盘、下载站、直播一起受影响

网站与其他业务彻底分开,互不拖累

登录入口

wp-login.php、xmlrpc.php 常年被爆破

只有管理员一个账号,通行密钥(Passkey)登录,无密码可爆破

会员 / 评论

开放注册、评论、论坛模块

全部关闭,没有公开账号

插件安全

插件与站点同权限运行

支持沙箱插件,按声明的权限授权

日常运维

更新 PHP、主题、插件,清日志,看磁盘

基本为零,升级时改版本号、部署即可

备份与回滚

宝塔备份 + 手动导出数据库

D1 时间点恢复 + 整站导出 + Worker 一键回滚

给 AI 读的内容

无

自动生成 /llms.txt、结构化数据,发布即推送 IndexNow

如果只能挑一行来说明这次迁移,我会选"被扫描时"那一行。以前被扫描是事故,现在被扫描只是 Cloudflare 日志里多了几行记录。

四、搬家是怎么做的

整个迁移用了一天多,9 月 28 日晚上正式切换上线。步骤大致如下,给想搬家的朋友参考。

EmDash 官方提供两种导入途径:在 WordPress 后台导出 WXR 文件,或者安装 EmDash Exporter 插件,附件媒体会自动迁进媒体库。我的站有不少定制需求,所以走了一条自己写脚本的路线:

第 1 步:把 WordPress 的内容完整拉下来。
用 WordPress 自带的 REST API 导出文章、分类、标签和 SEO 信息,存成 JSON 快照,作为迁移的唯一数据源。一共 37 篇文章、83 个标签。

第 2 步:把图片搬到本地。
60 张文章配图全部下载到本地备份,再统一上传到 R2。这里踩了一个坑:旧站对"非浏览器"的请求直接返回 404,而 Cloudflare 会把这个 404 缓存下来,导致真实访客也看到裂图。最后不得不去 Cloudflare 后台手动清掉缓存。教训:迁移脚本请求线上旧图时,要带上浏览器的 Accept 头,再加一个随机参数,绕开共享缓存。

第 3 步:生成种子文件,导入 EmDash。
把快照转换成 EmDash 的种子文件(seed),里面包括内容模型、页面区块、菜单、分类和全部文章。新建站点时选择导入种子,再跑脚本上传图片、恢复每篇文章原来的发布日期。

第 4 步:保住旧网址,SEO 一点不丢。
这是最重要的一步。旧文章的网址是 /247.html 这种格式,新站原样沿用,文章的 slug 就是原来的 WordPress ID。旧的图片地址 /wp-content/uploads/…、旧的搜索链接 /?s=、/?p= 全部 301 跳转到新地址。新写的文章也接着编号,从 935 开始。

第 5 步:整理排版。
写了一个脚本给旧文章统一格式:加粗行变成小标题、自动生成目录、编号段落变成列表。脚本在写入前会逐篇核对文字、链接、图片和代码与原文一致,只动格式,不动一个字。

第 6 步:部署和切换。
npm run deploy 一条命令构建并部署到 Cloudflare Workers,再把 baoge.vip 绑定为 Worker 的自定义域名。切换前在预览域名上验收了一遍;同时保留回滚方案:解绑域名、恢复原来的 DNS 记录,几分钟就能切回旧站。

如果你也想搬,最小的路径其实很短:

npm create emdash@latest
npm run dev        # 本地 http://localhost:4321/_emdash/admin
npm run deploy     # 部署到 Cloudflare

难的不是部署,而是迁移内容时"网址不变、图片不丢、格式不乱"这三件事。

五、搬完之后,也有代价

生态还很年轻

说清楚好处,也要说清楚代价:

  • 生态还很年轻。 EmDash 1.0 刚发布不久,没有 WordPress 那样海量的主题和插件。想要的功能,很多时候得自己写。
  • 要懂一点代码。 主题是 Astro 组件,定制页面要改代码。好在后台已经能覆盖日常的大部分操作。
  • 放弃了一些功能。 评论、会员、论坛我都关了。对我的站来说这些本来就是负担,但如果你的站靠社区运营,要慎重。
  • 备份方式不同。 D1 的原生导出不支持 EmDash 的全文搜索表,要用 EmDash 自带的整站导出,加上 D1 的时间点恢复。
  • 沙箱插件有门槛。 在 Cloudflare 上,EmDash 通过 Worker Loader 以 Dynamic Worker 的方式运行沙箱插件,这需要 Workers 付费计划。我现在用的两个插件(SEO 和配色)都是跟站点代码一起部署的原生插件,没有走沙箱,所以装什么插件仍然要自己把关。
  • 版本要锁死。 我把 EmDash 的版本号精确锁定,每次升级先读更新说明、先备份、本地验证,再上线。

六、写在最后

回头看,那个印尼扫描器反倒帮了我一个忙。它让我看清楚:对个人站长来说,最稀缺的不是服务器性能,而是注意力。每一台需要我盯着的服务器,每一个需要我记得更新的插件,都在消耗这种注意力。

现在的 baoge.vip 没有服务器可以被打满,没有登录页可以被爆破,旧文章的网址一个没变。我终于可以把时间花在写内容上,而不是守着 CPU 曲线。

再见了,WordPress。谢谢你这几年。

新站地址还是那个:https://baoge.vip ,欢迎来逛逛。


参考来源