从 Hexo 迁移到 WordPress

最近利用空闲时间把自己的博客从 Hexo 迁移到了 WordPress,是的,在时隔将近两年之后,我又一次从 Hexo 迁移回到了 WordPress,从 Hexo 到 WordPress 的迁移之路是非常漫长的,即使自己博客文章数量不是很多,但是还是花费了大半个晚上,终于差不多迁移好了,遂记录一下,分享出来。

Why WordPress

将近两年前,我从 WordPress 迁移到了 Hexo,现在又迁移回来了,我知道在全民 WordPress -> Hexo 的时代似乎这么 「逆行」 有点政治不正确,但是迁移到 WordPress 之后对于我来说有了以下特性:

  • 更好看的主题(唉我还是看脸了)
  • 更好的 SEO
  • 更加用户友好的评论系统
  • 定时文章发布功能
  • 更好的分类目录管理
  • 非常全面的插件库

Image Hosting

我的博客图片不多,但是 WordPress 对于图片的管理让用户不得不一直 Stick to 他们自己的媒体库,非常的不方便,于是将自己的博客图片全部托管在自己的机器上(本来还考虑过 Object Storage -> Nginx -> Cloudflare CDN 的,但是感觉那样太骚了,而且桶的权限也不很好设置),这样方便内容和图片分离,即使将来有进一步迁移的需求的话也不需要过于纠结图片如何导出的问题,毕竟:

  • 在 Hexo 上是 md 文件 + 外链图片
  • 在 WordPress 上是 xml 内容 + 外链图片 + 媒体库中存放的 Feature Image(装饰作用,丢了不可惜)

图床地址是: https://blog-assets.nova.moe,由于存放的图片都是博客上需要的图片,在 Cloudflare 端就直接使用了 Flexible SSL(其实主要是因为懒),且根据 Cloudflare 的文档:Which file extensions does Cloudflare cache for static content? ,Cloudflare 会所有图片缓存下来,至于在国内访问速度如何嘛…这是个玄学问题。

Export from Hexo

我的博客 RSS 默认是以 atom 方式输出文章摘要,这里需要调整为 rss2 格式输出全文方便 WordPress 导入,在 _config.yml 中配置如下:

feed:
  type: rss2
  path: atom.xml
  limit: 0
  hub:
  content: true

此时 hexo g 之后将生成的 atom.xml 文件导出出来,准备将博客的所有图片地址替换为自己的外链,这一步一开始我想的太复杂了,以为需要各种正则表达式匹配转换,后来想了一下,直接用查找&替换把所有的 /pics 替换成了 https://blog-assets.nova.moe/pics 就完事了~

Import to WordPress

WordPress 提供一个 RSS Importer,如果你和我一样使用着 PHP 7 的话,在导入的时候会看到一个异常,原因是在 /wp-content/plugins/rss-importer/rss-importer.php 的 72 行中有一个函数调用:

set_magic_quotes_runtime(0);

已经被弃用了,直接无脑把他注释掉即可~

成功导入后只是漫漫长路的第一步,因为你很快就会发现:

  • URL 全部乱了(变成了 /<标题>,而不是 /some-slug
  • 图片全部会超过边界(因为导入后只能使用 Classic Editor 而不能使用 Block Editor,如果需要 Convert 的话,所有的 pre 标签内容会全部毁掉,如下图)

对于这种情况…其实也是挺无解的,所以基本每篇文章都需要手动全部删除那个 Classic Block 并且手动复制一下 Markdown 文本上去。(虽然看上去像是完全重建了,但是这样导入 + 重新复制的方式可以减少手动构建文章结构以及日期等步骤)

Backups

这个步骤是通过计划任务自动备份到 Object Storage ,可以参考《在 Scaleway Object Storage 上備份數據》,此外,我会在每次文章发布的时候手动通过 WordPress 的工具 Export 一份作为备份,存放在 Object Storage 上。

此外,由于使用了外链图片,Wordpress 自带的 Export 功能完全足以用于博客文章的迁移,而且如果运气好的话还可以自动从原始站点(如果原始站点还在的话)下载 Featured Image。

RSS

这个也是需要考虑的,由于之前的博客的 RSS 输出地址是:/atom.xml 而现在是 /rss 或者 /feed 对于使用 RSS 阅读器的读者来说可能需要手动调整一下。

更新:已经通过创建一个 301 重定向解决,RSS 用户应该无需任何设置了。

Comments

不幸的是,Disqus 中的评论无法导入到 WordPress,所以…

Permission

在开了一个神奇的插件之后 WordPress 直接 500 了,非常迷,不过还好 10 分钟前有一个备份(论备份的重要性),不过从 Object Storage 上把自己的备份取下来后权限全部变成了 ubuntu:ubuntu,这样 WordPress 的所有权限全部就没有了,插件和上传功能全部损坏,这里通过一个脚本来进行修复,(我的 WordPress 是跑在 Docker 中的,Docker 中默认使用的 Apache 作为服务器,用户和权限都是 www-data)代码如下:

#!/bin/bash
WP_OWNER=www-data # <-- wordpress owner
WP_GROUP=www-data # <-- wordpress group
WP_ROOT=$1 # <-- wordpress root directory
WS_GROUP=www-data # <-- webserver group

# reset to safe defaults
find ${WP_ROOT} -exec chown ${WP_OWNER}:${WP_GROUP} {} \;
find ${WP_ROOT} -type d -exec chmod 755 {} \;
find ${WP_ROOT} -type f -exec chmod 644 {} \;

# allow wordpress to manage wp-config.php (but prevent world access)
chgrp ${WS_GROUP} ${WP_ROOT}/wp-config.php
chmod 660 ${WP_ROOT}/wp-config.php

# allow wordpress to manage wp-content
find ${WP_ROOT}/wp-content -exec chgrp ${WS_GROUP} {} \;
find ${WP_ROOT}/wp-content -type d -exec chmod 775 {} \;
find ${WP_ROOT}/wp-content -type f -exec chmod 664 {} \;

用法:

$ /path/to/this-script.sh /path/to/wordpress/

这样就可以快速恢复 Wordpres 的文件权限。

Forward compatibility

虽然上了 WordPress 的车,但是为了保证前向兼容,目前文章管理方式如下:

  1. 需要写一篇新的文章?
  2. hexo new draft new-blog-post-slug
  3. 用自己最喜欢的编辑器(Vim)写文章
  4. source 目录同步到 Object Storage
  5. Hexo 渲染 HTML 并同步到某服务器中
  6. WordPress 新建文章并且复制 Markdown 内容
  7. 在 WordPress 中对文章进行一些调整,发布

这样即使 WordPress 出了什么严重的问题(或者突然不喜欢了),我依然可以在较短的时间内通过 Hexo 顶上,并且给自己修理 WordPress 的时间。

What’s Next && Problems

  • 首先所有的评论都没有了,这一点似乎无法避免,如果有什么好的思路可以从 Disqus 中导入到 WordPress 中的话,欢迎来告知我。
  • 如果对于一篇已经发布的文章要进行修改的话,需要同时修改本地的 md 文件和 WordPress 端的数据。
  • 由于迁移期间有大量的手工操作,难免会有一个错误和疏漏,还需要在后期慢慢修改。

WordPress 作为一个动态程序,其稳定性和维护的成本是大于 Hexo 这类静态文章生成器的,安全性也是要大大降低的。不过…

翅膀长硬了总是要自己的飞的嘛,不能总是停留在心理舒适区中,用 md 写文章,然后 hexo g 推到 GitHub 上了事。

下一步的计划是通过定时任务实时检测站点的在线情况,若发现站点掉线( Response Code != 200),则自动从 Object Storage 中获取上一个备份并且尝试本地重建,若重建失败则通过 Cloudflare API 将站点 DNS 切换到 Hexo 的备份站点上,并且邮件通知我,如果你感觉这样很蛋疼的话,我也是这么认为的。:P

啊,WP 真香!