我是怎么对我的网站进行优化的(四):Speed

很多同学都说 WordPress 很慢,但是作为全世界最常用的建站和博客系统 WordPress 来说,我相信在性能设计上肯定不会有太大的问题,WordPress 开发团队也肯定也考虑到这个问题。其实我觉得,WordPress 并不慢,只是看你会不会用,就像 Windows、Android,有些人觉得不错,有些人觉得慢、差劲,其实也许是你会不会使用的问题。

主机自身的速度的确是影响网站速度最重要的一点,但除此之外,还受到其他很多方面的影响,比如安装太多效率低下的插件,使用代码质量低下的主题,没有正确使用 WordPress 的缓存等。

今天我就结合实例(本博客)来和大家分析一下这个问题。

首先说下,本博客托管在一般的虚拟主机上,并没有托管在 VPS、有 Memcached 等各种各样内存缓存的虚拟主机上,而且,本博客也没有用任何静态化缓存插件,因为我给博客配置了“手机版”,用这些插件特别容易出问题。

那么怎么去优化自身呢?

尽量减少使用插件

这是首要的一点。有句流行的话说过“能用代码解决的决不用插件”,但实际情况是大部分的人往往都没足够的代码知识,更不可能做到每个插件的代码化。所以,更好的选择是能不用的插件就不用。因为大部分的插件都会进行数据查询与生成,这在页面生成过程中将耗费时间。需要注意的是,尽量不要使用效率极低的插件,比如某些 SEO 插件,这完全是可以用代码实现的,对于某些插件仅有一个文件的,完全可以尝试自己简单修改、阅读,加入主题的 Functions.php 中,我相信对大部分喜欢折腾 WordPress 的人来说,没什么难度。

并且,插件大多都会在页面中载入各种各样的 CSS 和 JS,而网站优化中有2条内容是:

  • 减少HTTP请求,每一次对于JS,CSS等文件的访问都是一次HTTP请求。插件用得少,HTTP 请求数自然就变少了。
  • 合并 CSS 和 JS 文件,减少HTTP请求的首要办法是合并 CSS 和 JS。因为浏览器没有你们想象中的那么聪明,告诉一个令你们感到不可思议的事实——1个 10KB 的 JS 和2个 5KB 的  JS 载入所耗费的时间是不一样的,而且后者载入时间会明显增多。特别是文件都在同一域名下这样的情况更为明显。而插件的 JS 和 CSS 都是独立的,如果10个插件每个都生成1个 JS + 1个CSS,再加上主题的话,CSS 和 JS 的数量的数量可能会令你无法想象。当然,我也用了好多插件(20来个~),你要是有点水平的话,可以尝试自己合并,但是,我想说的是,个人建议不要使用自动合并插件,很多时候,出了问题,你也不知道该怎么办,甚至出了问题你还没有知道。

而且,对于不用插件的处理,我建议“删除”而不是简简单单的“禁用”。因为 WordPress 在每一次的页面访问时,都会判断插件的使用情况。让 WordPress 做更少的判断就等于做更少的数据查询。

使用经过优化的主题

如今 WordPress 主题是越来越绚丽,但请你们在使用这些主题时,考虑下主机能否带得动。而且,明显那些国外的主题(默认主题除外)不太适合我们,因为一些国外的主题往往使用了过多的 JS 和 CSS,人家带宽好,不怕这些,但我们 4M、6M 甚至有些地方还在用着 1M、2M 的宽带的人使用起来可就受苦了。当然,如果你会手动修改主题,使其能适应我们这种带宽的话,我没意见。

使用的主题尽量满足以下要求:

  • 合并 CSS 和 JS——尽量仅仅使用一个 JS 和一个 CSS
  • 正确放置 CSS 和 JS 的位置——尽量将 JS 放置到页面底部、CSS 放置到页面顶部(最好放在</head>之前)
  • 合并图片——尽量少使用图片,能的话,将主题图片使用 CSS Sprites 控制在1~2个
  • 减少数据查询——尽量少使用数据查询,能直接输出的就不要用数据查询

对页面进行 GZip 压缩

使用 GZip 压缩至少可以减少网页体积20%(静态资源除外)。通常大部分的优秀主机都能够支持服务端的 GZip 并且可以自动压缩。如果服务器没有自动进行页面压缩,就需要自行开启。如何开启,我就不多说了,这个请自己百度,寻找适合的方法。

使用 CDN 加速静态资源

网站的静态文件一般有两种:第一种是网站的 CSS,JS 和一些主题的常用背景图片和按钮文件,这些图片如果网站不进行改版或者其他改动,基本上是不会修改的,第二种是每天更新的网站内容中上传的图片或者附件,这些图片文件也是基本不会改动的。

解决好静态文件存储和加速,网站性能就首先能得到基本的保证了,WordPress 构建的网站和博客也是一样的。对于这些静态文件来说,最好的解决方案永远是使用 CDN 网络进行加速,这样服务器的压力将大大降低,因为访问页面只有当前页面是在自己服务器上,其他所有图片 JS CSS 都是从 CDN 获取的。

从使用便捷性和性价比角度来说,个人推荐七牛云存储。

正确使用缓存插件

这个要跟据你的实际情况使用,比如本博客使用的是 WP File Cache + DB Cache Reloaded Fix,考虑到 WP File Cache,网上还没有教程,有时间我再写一个吧!

有效利用 WordPress 自身缓存机制——对象缓存

要彻底明白和搞懂 WordPress 性能优化,首先要理解 WordPress 缓存机制,WordPress 默认是一种叫做 WordPress Object Cache 的对象缓存机制,它把需要缓存的内容按照 Key-Value 这样的模式进行缓存(和 No-SQL 的 key-value 的有点类似),当然它还支持按照 Group 来划分和避免缓存的内容冲突。

所以最基础的 WordPress 缓存就是,把 WordPress 产生的 Key-Value 缓存起来。比如存到文件(文件缓存),或者存到内存(内存缓存)。

由此得知,WordPress 主题和插件尽量使用模板函数,因为 WordPress 模板函数如果部分已经做好了 WordPress Object Cache。
比如 get_the_terms 和 wp_get_object_terms 这两个函数,功能基本一样,但是 get_the_terms 直接从对象缓存中取数据,无查询,而 wp_get_object_terms 每次都从数据库中取数据。

WordPress 插件和主题如果一定要直接查询数据库,请做好 WordPress Object Cache,将查询的结果使用 wp_cahce_set 存到 Object Cache 中,下次直接使用 wp_cache_get 获取。

不过,需要注意的是,别过度,比如某些已经使用过 WordPress Object Cache 的模版函数,就不要自作多情再增加一个了,那样会更慢。

用好 WordPress Transients API

Transients 是瞬时的意思,WordPress 的 Transients API 就是 WordPress 用来存储一些缓存的数据到数据库中最简单也是最标准的方法,Transients API 给这些缓存的数据一个过期时间,并且时间已到就会自动删除,所以如果你需要存储一些有生命周期的选项的时候,Transients API 就是最好的选择。

这难道同样不是我们做缓存的最佳选择么?

尽量不使用 WordPress 小工具

WordPress 小工具其实是速度变慢的根源之一,因为这会引发许许多多的数据查询。所以,尝试自己手写 SideBar 吧,这并不难。而且,这样也有利于我们使用 WordPress Transients API 和 WordPress Object Cache。

WordPress 缓存插件 WP File Cache 安装与使用

上篇文章《我是怎么对我的网站进行优化的(四):Speed》提到要写这么一个教程,那我就写一写吧!其实 WP File Cache 并“人如其名”,而是对 WordPress Object Cache 的优化。

介绍

The plugin implements object level persistent caching and can be used instead of the built in WordPress WP_Object_Cache. Unlike WP Super Cache, Hyper Cache and other plugins, WP File Cache does not cache the entire page; instead, it caches the data WordPress explicitly asks it to cache (using wp_cache_xxx() API functions). Although this means that the performance will be less than with, say, WP Super Cache, all your pages remain dynamic. WP File Cache won’t help you much if the plugins or theme you are using do not use WordPress Cache API. This is by design, since the plugin tries to play nice. However, for most WordPress installations this will not be critical.

简单来说,这个插件就是将 WordPress Object Cache 保存到文件(所以需要配合 WordPress Object Cache 使用,要不没那么明显的效果),这可是我们这些无法上内存缓存的小家伙的福音。明显的,这个插件要主机的硬盘 I/O 比较好才行。

不过,那些财大气粗,可以上内存缓存的家伙,就不要去使用了,用好你的内存缓存吧!无论怎么样,内存缓存总比文件缓存的效率高。

而且,这个插件不同于 WP Super Cache、Hyper Cache 等插件,所以,你安装完这个后,如果没有我那种特殊需求,你还可以在安装其它的缓存插件,会达到更明显的加速效果。

安装使用

怎么安装就不用我教了吧?后台搜索“WP File Cache”,安装即可。借用“大猫”的一句话:神马FTP时代,全部都过去了。

然后,勾上“Enable WP File Cache”和“Save cached data across sessions”,轻点下“Save Changes“,不必退出登录,如果你的主题优化的足够好的话,立刻就可以体验到飞一般的效果了。

安装后出现了一些莫名其妙的问题,怎么办?

So Easy!勾上“Do not use cache in the Admin Panel”,问题应该自解了。如果还不能解决,只能卸载插件了,说明你不适合用这个插件。

换了个主题——ProwerV6

思量再三,换成了 ProwerV6 这个主题,把用了许多年的 iGoogler 主题换掉了。为什么要换呢?因为——响应式设计。这可以省掉插件。但是,问题就来了——不支持IE6,这个真的没办法,算了吧。

旧主题的各种优化教程,我还是会发,算是为 iGoogler 主题做的最后一点贡献。

找不到“友情链接”的博主,请留意底部。

又换了个主题,Clean Retina

因为原主题在某些特殊IE内核浏览器的侧边栏会出问题,不用侧边栏又不爽,所以又换了一个主题。加上学习一下 WordPress 子主题的制作,在每天挤出短短时间,使用 WordPress 子主题方式做出了这个主题。

部分修改:

  • 增加版权信息提示
  • 修改底部
  • 完善 Google 结构化数据
  • 添加“无插件”PageNavi
  • 汉化部分
  • 合并 JS、CSS 文件

而且,这个主题支持 Retina 显示屏,不错,但是不好的地方是需要加载的 JS 太多了,我调了半天,勉强不需要那么多了。

iGoogler 优化教程(一):使用 WordPress Object Cache

这个教程主要是方便和我一样使用 iGoogler 主题的人,能给自己的站点提一下速。因为一个效率优化做得那么好的主题,如果你还觉得速度慢,那真的是你不会使用了。

WordPress Object Cache 简介

WordPress Object Cache(WordPress 对象缓存)是 WordPress 自身的缓存机制,它的主要功能是把负责查询或者运算的结果按照 Key-Value 这样的方式(WordPress 还支持按照 Group 来划分和避免缓存的内容冲突)存储到对象里面,下次进行同样操作的时候,可以让直接从这个对象中取出数据,不用重复到数据库中或者其他外部网站获取数据。

由于 WordPress Object Cache 的特性,这个自身的缓存机制注定要配合服务器设置(财大气粗呀~)以及插件。如果你和我一样,没办法接触到类似于 Memcached 之类的东西的话,我推荐你使用 WP File Cache,他能帮助你把数据查询缓存到文件中。这样效率和速度都非常快的。如果不配合服务器设置和插件的话,个人感觉是没有什么作用的。

使用 WordPress Object Cache

下面我将以 iGoogler 主题的“相关文章”为例,说一下如何使用 WordPress Object Cache。

我们知道 “相关文章”的获取原理是通过文章的 Tags 来获取相关文章,相同的 Tag 越多,相关性越强,这样就需要进行大量的数据查询,大大降低了站点的效率。但是,一篇文章,在短时间内,它的“相关文章”是不会变动的,所以我们就可以使用 WordPress Object Cache 对“相关文章”进行加速。

下面是把“相关文章”的数据写入缓存的例子,缓存时间为一个小时,即 3600 秒。

打开主题的 loop_single.php,将

<?php echo wp_get_related_posts_igoogler(10); ?>

替换为

<?php
global $post;
$related_posts_data = wp_cache_get($post->ID, 'related_posts');
if(false === $related_posts_data){
	$related_posts_data = wp_get_related_posts_igoogler(10);
	wp_cache_set($post->ID, $related_posts_data, 'related_posts', 3600);
}
echo $related_posts_data;
?>

代码大意是:如果在缓存中找不到数据,就查询数据库,然后再将数据写入缓存,并设定过期时间为一个小时,即 3600 秒;如果找得到缓存,并且缓存没有过期,就直接使用缓存的数据。

iGoogler 优化教程(二):使用 WordPress Transients API

这个教程主要是方便和我一样使用 iGoogler 主题的人,能给自己的站点提一下速。因为一个效率优化做得那么好的主题,如果你还觉得速度慢,那真的是你不会使用了。

WordPress Transients API 简介

Transients 是瞬时的意思,WordPress 的 Transients API 就是 WordPress 用来存储一些缓存的数据到数据库中最简单也是最标准的方法,Transients API 给这些缓存的数据一个过期时间,并且时间到就会自动删除,所以如果你需要存储一些有生命周期的选项的时候,Transients API 就是最好的选择。

更让人感到欣喜的是,WordPress Transients API 不需要配合任何的服务器设置和插件。

使用 WordPress Transients API

下面我将以 iGoogler 主题的“最多评论的文章”为例,说一下如何使用 WordPress Transients API。

我们知道 “最多评论的文章”的获取需要进行大量的数据查询,大大降低了站点的效率。但是在短时间内,一个博客的“最多评论的文章”是不会变动的,所以我们就可以使用 WordPress Transients API 对“最多评论的文章”进行加速。

下面是把“相关文章”的数据写入缓存的例子,缓存时间为一天,即 86400 秒。

打开主题的 sidebar_r.php,将

<?php echo get_most_comments_posts_igoogler(5);?>

替换为

<?php
$most_comments_posts_data = get_transient('most_comments_posts');
if(false === $most_comments_posts_data){
	$most_comments_posts_data = get_most_comments_posts_igoogler(5);
	set_transient('most_comments_posts', $most_comments_posts_data, 86400);
}
echo $most_comments_posts_data;
?>

代码大意是:如果在缓存中找不到数据,就查询数据库,然后再将数据写入缓存,并设定过期时间为一天,即 86400 秒;如果找得到缓存,并且缓存没有过期,就直接使用缓存的数据。

由于我的博客较小,所以不需要太短的时间(在短时间内不会变动),如果你的博客较大,并且配上了其他缓存插件,你可以尝试使用“我爱水煮鱼”推荐的一个值——12 小时,即 43200 秒。

iGoogler 优化教程(三):巧用 PostMeta 提速

这个教程主要是方便和我一样使用 iGoogler 主题的人,能给自己的站点提一下速。因为一个效率优化做得那么好的主题,如果你还觉得速度慢,那真的是你不会使用了。

下面我将以 iGoogler 主题的“相关文章”为例,说一下如何巧用 PostMeta 提速。

我们知道 “相关文章”的获取原理是通过文章的 Tags 来获取相关文章,相同的 Tag 越多,相关性越强,这样就需要进行大量的数据查询,大大降低了站点的效率。但是,一篇文章,在短时间内,它的“相关文章”是不会变动的。所以我们就可以使用缓存对“相关文章”进行加速。

第一个方法是使用 WordPress Object Cache,这个方法需要配合服务器设置或插件,,否则基本没用,这也许会令某些人大感不爽。

所以下面我就要讲第二个方法——巧用 PostMeta:

PostMeta 加速原理

我们知道,PostMeta 表是用来存储 Post 其他自定义字段,比如你可以在 WordPress 编辑界面自定义字段那里使用它。那么我可以把当前文章的“相关文章”数据写到 PostMeta 中去,并记录写入的时间。然后再取出,就可以达到加速的效果。

巧用 PostMeta 提速

下面是把“相关文章”的数据写入缓存(PostMeta)的例子,缓存时间为一个小时,即 3600 秒。

打开主题的 loop_single.php,将

<?php echo wp_get_related_posts_igoogler(10); ?>

替换为

<?php
global $id;
$related_posts_data_old = get_post_meta($id, "related_posts", $single = true);
if($related_posts_data_old){
	$time = time();
	if(($time - $related_posts_data_old["time"]) < 3600){
		echo $related_posts_data_old["related_posts"];
	}
}else{
	$related_posts_data = wp_get_related_posts_igoogler(10);
	$related_posts_data_new = array("time"=>time(), "related_posts"=>$related_posts_data);
	if($related_posts_data_old){
		update_post_meta($id, 'related_posts', $related_posts_data_new);
	}else{
		add_post_meta($id, 'related_posts', $related_posts_data_new, true);
	}
	echo $related_posts_data;
}
?>

代码大意是:如果在缓存(PostMeta)中找不到数据,就查询数据库,然后再将数据写入缓存,并设定过期时间为一个小时,即 3600 秒;如果找得到缓存,并且缓存没有过期,就直接使用缓存的数据。

沁园春 • 放学

今天在网上看到一个很有意思的段子,在接送回家的路上,深有所感,略作修改:

放学路上,千里车流,万里人潮。望大街内外,车行如龟,司机烦躁,一步不动,总是红灯憋出尿。交通如此多焦,引无数学生上公交。惜奥迪A6,慢如蜗牛。奔驰宝马,无处发飙。一代天骄,兰博基尼,泪看电驴子把车超。俱往矣,还数自行车,边蹬边笑。

其实这首诗有点儿万能,很多都能套上去。

iGoogler 优化教程(四):手写侧边栏提速

这个教程主要是方便和我一样使用 iGoogler 主题的人,能给自己的站点提一下速。因为一个效率优化做得那么好的主题,如果你还觉得速度慢,那真的是你不会使用了。WordPress 小工具其实是速度变慢的根源之一,因为这会引发许许多多的数据查询。所以,尝试自己手写 SideBar 吧,这并不难。而且,这样也有利于我们使用 WordPress Transients APIWordPress Object Cache 等缓存。

如果你不会写,那么可以参考我的:

打开主题的 sidebar_l.php,全部替换为:

<h3 class="lbar_title">
	<a><?php _e('分类目录')?> </a>
</h3>
<div class="lbar_content">
	<ul>
		<?php wp_list_categories('show_count=1&hierarchical=1depth=2&title_li='); ?>
	</ul>
</div>
<h3 class="lbar_title">
	<a><?php _e('时间选择');?> </a>
</h3>
<div class="lbar_content">
	<ul>
		<?php wp_get_archives(); ?>
	</ul>
</div>
<h3 class="lbar_title">
	<a><?php _e('标签云')?> </a>
</h3>
<div class="lbar_content">
	<ul>
		<?php wp_tag_cloud('smallest=10&largest=14&number=20&order=RAND'); ?>
	</ul>
</div>
<h3 class="lbar_title">
	<a class="current"><?php _e('友情链接')?> </a>
</h3>
<div class="lbar_content" style="display:block;">
	<ul>
		<?php wp_list_bookmarks('title_li=&categorize=0');?>
	</ul>
</div>
<div class="line"></div>

打开主题的 sidebar_r.php,全部替换为:

<h3>最新文章</h3>
<ul>
	<?php echo get_latest_posts_igoogler(5); ?>
</ul>
<h3>随便看看</h3>
<ul>
	<?php echo get_random_posts_igoogler(5); ?>
</ul>
<h3>最受欢迎</h3>
<ul>
	<?php
	$most_comments_posts_data = get_transient('most_comments_posts');
	if(false === $most_comments_posts_data){
		$most_comments_posts_data = get_most_comments_posts_igoogler(5);
		set_transient('most_comments_posts', $most_comments_posts_data, 86400);
	}
	echo $most_comments_posts_data;
	?>
</ul>

效果可参考本站。