为什么要搬
原来的博客系统使用的是Typecho,一个轻量、高效、快速的博客系统(至今也是)。但是Typecho的正式版已经很久没有更新,其中部分功能甚至无法兼容PHP 7;开发版虽然仍在坚持更新,但是也容易与各种过老的插件和主题产生兼容问题,并且社区的活跃度也略低,开发兴趣不高,最终导致的结果就是插件和主题不够多,功能实现全靠自己写的情况。而现在将全站迁移至WordPress也是无奈之举,一方面是更好的生态,意味着更多插件和主题选择,减少了重复造轮子魔改程序的情况,另一方面是WordPress有更频繁的更新频率,漏洞和Bug能更快得到修补。(等啥时候Typecho重出江湖我就换回来?)
怎么搬的
从Typecho导出
非常简单
- 使用ByeTyp插件将原博客数据导出为WordPress可识别的xml格式
- 使用Tp2MD插件导出Markdown格式的文章
GitHub
sunxiyuan/ByeTyp
GitHub
AlanDecode/Typecho-Plugin-Tp2MD
导入到WordPress
非常麻烦
- 安装WordPress
- 导入xml文件
- 进入文章编辑界面,将文章手动替换为Markdown文件(默认导入为html格式)
- 对WordPress进行调整优化
为什么要用Markdown
- 简洁
- 输出格式稳定
- 自由调节样式
- Gutenberg sucks
对WordPress做了什么
基本优化
- 使用WPJAM Basic这款插件,可以实现几乎所有在这篇文章中提到的所有优化
进阶优化
Object Cache
WordPress自带缓存机制,可以通过插件或在在wp-content
目录下建立object-cache.php
文件,实现使用Memcached/Redis对数据库请求进行缓存,可以减少大量SQL请求。
缓存插件
- WP Super Cache
- W3 Total Cache
- WP Rocket (收费)
CDN / Lazyload / 图片压缩
代码级优化
此处使用了Blackfire工具,对WordPress页面执行时间进行了简单分析,相对于自带的xdebug扩展,Blackfire更加灵活,可以将服务端和客户端分开部署,无需本地调试,生成的性能分析也很详细,诸如CPU Time, I/O Wait, Peak Memory等指标都可以查看,还有函数执行顺序可视化,Timeline这些功能,大大简化了对代码的分析过程。后续可能会新开一个坑,探索一下更多用法。
MO文件的缓存机制
非英文的WordPress在运行时,对于每个页面都会调用加载.mo文件,在翻译子系统上耗费大量计算性能,此处可以使用Speed Up - Translation Cache
这个插件,将.mo文件作为Object Cache,在本站上测试可以提高30%的页面生成速度。
避免使用 SQL_CALC_FOUND_ROWS (可选)
在数据量大时,这条命令会非常慢,所以我们将其重写,在主题function.php
或者Code Snippets中增加以下代码。
//设置WP_Query的 'no_found_rows' 属性为true,禁用SQL_CALC_FOUND_ROWS
if ( !function_exists( 'set_no_found_rows' ) ) {
function set_no_found_rows(WP_Query $wp_query)
{
$wp_query->set('no_found_rows', true);
}
}
add_filter( 'pre_get_posts', 'set_no_found_rows', 10, 1 );
if ( !function_exists( 'set_found_posts' ) ) {
function set_found_posts($clauses, WP_Query $wp_query)
{
// Don't proceed if it's a singular page.
if ($wp_query->is_singular()) {
return $clauses;
}
global $wpdb;
$where = isset($clauses['where']) ? $clauses['where'] : '';
$join = isset($clauses['join']) ? $clauses['join'] : '';
$distinct = isset($clauses['distinct']) ? $clauses['distinct'] : '';
//使用 EXPLAIN 方式重构
$wp_query->found_posts = (int)$wpdb->get_row("EXPLAIN SELECT $distinct * FROM {$wpdb->posts} $join WHERE 1=1 $where")->rows;
$posts_per_page = (!empty($wp_query->query_vars['posts_per_page']) ? absint($wp_query->query_vars['posts_per_page']) : absint(get_option('posts_per_page')));
$wp_query->max_num_pages = ceil($wp_query->found_posts / $posts_per_page);
return $clauses;
}
}
add_filter( 'posts_clauses', 'set_found_posts', 10, 2 );
我们仍未知道那天该如何解决的 apply_filters 函数
众所周知,WordPress提供了强大的各种Hook,大大降低了编写插件和主题的难度。由此带来的反面结果就是,大量的apply_filters
函数拖慢了页面加载时间。以本博客为例,在Blackfire中可以看到,apply_filters
函数被调用了近600次,耗费了200ms时间,但是很不幸,目前没有办法解决,只能希望WordPress在后续版本中优化性能。
安全加固
- 保持你的WordPress为较新版本
- 做好服务器防火墙、权限管理等安全策略
- 使用2FA及验证码等方式防止爆破登录
- Hide My WP 等隐藏插件
- 安全加固插件,定期扫描目录
- 禁止
wp-content/uploads
目录下代码执行
个人使用的插件
- Akismet
- Code Snippets
- Redis Object Cache
- Speed Up - Translation Cache
- Wordfence Login Security
- WP Githuber MD
- WP-Optimize
- WPJAM BASIC
- WP Super Cache