简化 WP Super Cache 的 Rewrite 规则

WP Super Cache 是一个很不错的插件,至少它的想法很不错。但是,它的代码相当得烂,烂到我一度怀疑插件作者是不是野生程序员,或者 PHP 程序员都是这种水平。

WP Super Cache 的一个功能是通过 Apache 的 URL 重写(Rewrite)来提供缓存,如果缓存存在,就不用使用 PHP 解析了,以提升响应速度。使用 URL 重写的方式是写一堆的重写规则(RewriteRule),告诉 Apache 如何把用户访问的 URL 转换到本地缓存的地址。

WP Super Cache 的默认重写规则是这样的:

如果你仔细观查,会发现除了第一行 RewriteBase 外,后面的四段是几乎一模一样的,唯一的差别是 HTTPS 和 .gz。这两种情况分别有是与否两种可能,于是乘一乘总共就是四种形态。只不过,我很想问一下插件作者,你不会使用变量吗?非要写四段一模一样的。

以下是我的简化版:

由于我不需要 .gz,就把那段直接删掉了。其实 .gz 和 .html 是只要一个就可以的,如果你需要 .gz 格式,就在最后两行的 .html 后面加上 .gz 即可。我的改动主要是把 HTTPS 变量抽出来,做成一个环境变量(Environment Variable),就是 SetEnvIfExpr 那一段。SetEnvIfExpr 会在所有 RewriteRule之前执行,于是下面的 RewriteRule 就可以得到确切的值。

为什么要这样修改?Apache 的重写规则的执行方式,并不是从上到下一遍执行完即可。它的方式是,当一条 RewriteRule 执行完成之后,即 URL 变成了一个新的值之后,会再交给剩下所有的 RewriteRule 重新尝试重写一下,即使这个 RewriteRule 的条件(RewriteCond)没有达到,也会尝试一下,直到没有一条 RewriteRule 能起作用为止。也就是说,Super Cache 新加的四条 RewriteRule 和其之前的一大段 RewriteCond 会被反复执行很多遍,这样效率就差了。合并成一条之后,效率为提升(尽管可能观察不到),代码的可维护性也好了很多。

顺便分享一些小贴示:

  • 我发现 mod_dir 会干扰首页的缓存,使得首页一直无法从缓存加载,把 mod_dir 禁用掉即可。当然由于 mod_dir 的作用比较大,你可能需要做一些其它的改动才能使博客正常运行;
  • 如果你有权限修改 VHost,那就不要使用 .htaccess。.htaccess 文件会在每一个 HTTP 请求的时候,都重新被 Apache 加载一遍,效率很差,而 VHost 只在 Apache 重启的时候才加载。

15 条评论 添加

    1. 我之前也考虑过使用不依赖于 WordPress 的缓存机制,但问题是判断页面是否有刷新太麻烦了,不判断的话就不能设制很长时间的缓存,否则用户看不到最新的留言。现在 Super Cache 的缓存是一天,只有在页面更新的时候才刷新缓存。

      1. 话说,不挂代理上不了。dns找不到。
        The server at leonax.net can't be found, because the DNS lookup failed.

        我一开始在想分离评论,后来直接缓存页面,评论文章变更时更新单页面缓存。

        1. 貌似最近对 Google 的限制又严格了,我花了点时间更新了一下 DNS 服务器,过几天看看效果吧

          在 WordPress 中分离评论貌似很麻烦的样子。

发表评论

电子邮件地址不会被公开。 必填项已用*标注