作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Martín Di Felice
验证专家 在工程
18 的经验

Martin是一个拥有9年Wordpress和后端开发项目经验的全栈开发人员.

专业知识

分享

今天,WordPress功能强大 超过30%的互联网. 它很容易使用,非常受欢迎,而且短期内不会消失.

但是WordPress可能很慢. 那么如何优化它呢?

有很多关于如何调整和优化WordPress的文章. 事实上,WordPress本身提供了一个 健壮的指南 关于WordPress优化.

在很大程度上, 这些文章和教程涵盖了非常基本但有用的概念, 比如使用缓存插件, 与内容交付网络(cdn)集成, 尽量减少请求. 虽然这些建议非常有效,甚至是必要的, 最后, 他们没有解决根本的问题:大多数慢的WordPress站点都是糟糕或低效的代码造成的.

优化WordPress性能的高级指南

WordPress可能很慢,但它不必如此.

因此,本文主要旨在为开发人员提供 WordPress开发公司 有一些指导方针,可以帮助他们解决许多WordPress性能问题的根本原因.

WordPress提供了许多经常被开发人员忽视的性能导向特性. 没有利用这些特性的代码会拖慢最简单的任务 , 比如取柱子. 本文详细介绍了四种可能的解决方案, 如何解决WordPress性能缓慢背后的一些潜在问题.

抓取文章

WordPress提供了从数据库中获取任何类型文章的可能性. 有三种基本方法:

  • 使用 查询_posts () 功能: 这是一种非常直接的方法,但问题是它覆盖了主要方法 查询,这可能会导致不便. 例如, 这可能是一个问题,如果我们想确定, 在获取帖子后的某个时刻(例如在内部) footer.php),我们正在处理的是哪种页面. 事实上, 官方文档有一个说明,建议不要使用这个函数,因为您需要调用一个额外的函数来恢复原始查询. 此外,替换主查询将对页面加载时间产生负面影响.

  • 使用 get_posts () 功能: 这就像 查询_posts (),但它不会修改主查询. 另一方面, get_posts () 属性执行查询 suppress_filters 参数设置为 真正的. 这可能导致不一致, 特别是当我们在代码中使用与查询相关的过滤器时, 因为您在页面中不期望的帖子可能会被此函数返回.

  • 使用 WP_Query 类: 在我看来,这是从数据库中检索帖子的最好方法. 它不会改变主查询, 它以标准的方式执行, 就像任何其他WordPress查询一样.

但是无论我们使用哪种方法与数据库交互, 我们还需要考虑其他事情.

限制查询

我们应该总是指定查询必须获取多少篇文章.

为了实现这一点,我们使用 posts_per_page 参数.

WordPress允许我们指定-1作为该参数的可能值, 在这种情况下,系统将尝试获取满足定义条件的所有帖子.

这不是一个好的做法, 即使我们确定我们只会得到一些结果作为响应.

首先,我们很少能确定只得到一些结果. 即使我们可以, 不设置限制将要求数据库引擎扫描整个数据库查找匹配项.

相反, 限制结果通常使数据库引擎只能部分扫描数据, 这意味着更少的处理时间和更快的响应.

WordPress默认做的另一件事, 哪些会对性能产生负面影响, 它是否试图带来粘性帖子并计算在查询中发现了多少行.

然而,通常我们并不真的需要这些信息. 添加这两个参数将禁用这些功能并加快查询速度:

$查询 = new WP_Query(数组)
	“ignore_sticky_posts”	=> 真正的,
	“no_found_rows”		=> 真正的
	)
); 

从查询中排除帖子

从查询中排除帖子

有时我们希望从查询中排除某些帖子. WordPress提供了一个非常直接的实现方法:使用 post__not_in 参数. 例如:

posts_to_exclude美元 	= 数组(1,2,3);
posts_per_page美元	= 10;


$查询 = new WP_Query(数组)
	“posts_per_page”	=> posts_per_page美元,
	“post__not_in”		=> posts_to_exclude美元
	)
);


for ( $i = 0; $i < count( $查询->posts ); $i++ ) {
	//do stuff with $查询->posts[ $i ]
}

但是,虽然这非常简单,但它不是最优的,因为它在内部生成一个子查询. 特别是在大型安装中,这可能导致响应缓慢. 让PHP解释器通过一些简单的修改来完成这个处理会更快:

posts_to_exclude美元 	= 数组(1,2,3);
posts_per_page美元	= 10;


$查询 = new WP_Query(数组)
	“posts_per_page”	=> posts_per_page美元 + count( posts_to_exclude美元 )
	)
);


for ( $i = 0; $i < count( $查询->posts ) && $i < posts_per_page美元; $i++ ) {
	if ( ! in_数组( $查询->posts[ $i ]->ID, posts_to_exclude美元 ) ) {
		//do stuff with $查询->posts[ $i ]
	}
}

我在那里做了什么?

基本上, 我从数据库引擎中卸下了一些工作,把它留给了PHP引擎, 在内存中做同样的事情, 这样更快.

如何?

首先,我去掉了 post__not_in 参数。.

由于查询可能会给我们带来一些我们不想要的帖子,所以我增加了 posts_per_page 参数. 这样我就可以确保,即使我的回复中有一些不喜欢的帖子,我至少会 posts_per_page美元 期望职位.

然后,当我循环遍历这些帖子时,我只处理那些不在 posts_to_exclude美元 数组.

避免复杂的参数化

所有这些 查询方法 提供多种获取帖子的可能性:按类别, 通过元键或值, 按日期, 作者, 等.

虽然这种灵活性是一个强大的功能, 应该谨慎使用它,因为参数化可能转化为复杂的表连接和昂贵的数据库操作.

在下一节中, 我们将概述一种优雅的方式,在不影响性能的情况下仍然实现类似的功能.

最大限度地利用WordPress选项

WordPress Options API 提供一系列工具,方便地加载或保存数据. 它在处理小块信息时很有用, WordPress提供的其他机制(如帖子或分类法)过于复杂.

Wordpress选项优化

例如, 如果我们想要存储身份验证密钥或网站标题的背景颜色, 选择是我们所要寻找的.

WordPress不仅为我们提供了处理它们的函数, 但它也使我们能够以最有效的方式做到这一点.

时,甚至直接加载了一些选项 系统启动, 从而为我们提供了更快的访问(当创建一个新选项时), 我们需要考虑是否要自动加载它。.

考虑, 例如, 一个网站上,我们有一个旋转木马显示突发新闻指定后端. 我们的第一反应是使用如下的元键:

/ /函数.php
Add_action ('save_post', function ($post_id) {
	//为简单起见,我们在保存之前不包含所有必需的验证
	//元键:检查nonces,检查post类型和状态,检查
	//它不是一个修订或自动保存,等等.
	$post_id, 'is_breaking_news', ! empty ($_POST['is_breaking_news']));
} );


/ /头版.php
$查询 = new WP_Query(数组)
	“posts_per_page”	=> 1,
	“meta_key”		=> 'is_breaking_news'
	)
);
$breaking_news = $查询->posts[0] ?:空;

正如您所看到的,这种方法非常简单,但并不是最优的. 它将执行数据库查询,试图找到具有特定元键的帖子. 我们可以使用一个选项来实现类似的结果:

/ /函数.php
Add_action ('save_post', function ($post_id) {
	//与post验证相同
	if ( ! empty ($_POST['is_breaking_news']))
		Update_option ('breaking_news_id', $post_id);
} );


/ /头版.php
$breaking_news_id = get_option('breaking_news_id')
	$breaking_news = get_post($breaking_news_id);
其他的
	$breaking_news = NULL;

每个示例的功能略有不同.

在第一段代码中, 我们将永远得到最新的突发新闻, 就这篇文章的发布日期而言.

在第二个例子中, 每次有新帖子被设为突发新闻, 它将覆盖之前的突发新闻.

但因为我们可能一次只需要一个突发新闻,所以这应该不是问题.

最后,我们使用 WP_Query 使用元键)转换为简单而直接的查询(调用 get_post ()),这是一种更好、更高效的方法.

我们也可以做一个小的改变,使用瞬态而不是选项.

瞬态的工作原理类似,但允许我们指定一个过期时间.

例如, 突发新闻, 它非常合适,因为我们不想要一个旧的帖子作为突发新闻, 如果我们把改变或消除突发新闻的任务留给管理员, 他可能会忘记做这件事. 因此,通过两个简单的更改,我们添加了一个截止日期:

/ /函数.php
Add_action ('save_post', function ($post_id) {
	//与post验证相同
	
	//假设我们想要一个小时的突发新闻
	//(3600 =一小时内的秒数).
	if ( ! empty ($_POST['is_breaking_news']))
		Set_transient ('breaking_news_id', $post_id, 3600); 
} );


/ /头版.php
$breaking_news_id = get_transient('breaking_news_id')
	$breaking_news = get_post($breaking_news_id);
其他的
	$breaking_news = NULL;

启用持久缓存

WordPress本身就有 对象缓存机制.

例如,使用该机制缓存选项.

但, 默认情况下, 缓存不是持久化的, 这意味着它只在单个请求的持续时间内存在. 所有数据都缓存在内存中,以便更快地访问,但仅在该请求期间可用.

持久缓存说明

支持持久缓存需要安装持久缓存插件.

一些全页缓存插件附带了持久缓存插件(例如W3 Total cache)。, 但其他人则不然, 我们需要单独安装.

这将取决于我们平台的架构, 我们是否会使用文件, Memcached或其他存储缓存数据的机制, 但是我们应该利用这个惊人的特性.

有人可能会问:“如果这是一个很棒的功能,为什么WordPress不默认启用它?”?

主要原因是, 这取决于我们平台的架构, 有些缓存技术可以工作,有些则不行.

如果我们将网站托管在分布式服务器上, 例如, 我们应该使用外部缓存系统, (例如 Memcached 服务器), 但如果我们的网站驻留在一台服务器上, 我们可以通过简单地使用文件系统来缓存来节省一些钱.

我们需要考虑的一件事是缓存过期. 这是使用持久缓存时最常见的陷阱.

如果我们不能正确处理这个问题, 我们的用户会抱怨他们看不到他们所做的更改,或者他们的更改花了太长时间才应用.

有时我们会发现自己在性能和动态之间做出权衡, 但即使有这些障碍, 持久缓存实际上是每个WordPress安装都应该利用的功能.

最快的方式

如果我们需要通过AJAX与我们的网站沟通,WordPress 提供了一些抽象 在服务器端处理请求时.

尽管这些技术可以在编程后端工具或从前端提交表单时使用, 如果不是绝对必要的话,应该避免使用.

这样做的原因是为了使用这些机制, 我们有义务向位于。中的某个文件发出post请求 wp-admin 文件夹. 大多数(如果不是全部的话)WordPress全页缓存插件既不缓存帖子请求,也不缓存对管理员文件的调用.

例如, 如果我们动态加载更多的帖子,当用户滚动我们的主页, 最好直接调用其他一些前端页面, 哪一个将获得缓存的好处.

然后我们可以在浏览器中通过JavaScript解析结果.

是的, 我们发送的数据比我们需要的要多, 但我们在处理速度和响应时间方面是领先的.

不要认为WordPress太慢了

这些只是开发者在编写代码时应该考虑的一些建议 WordPress.

有时, 我们忘记了我们的插件或主题可能需要与其他插件一起生活, 或者,我们的网站可能由托管公司提供服务,该公司为数百或数千个其他网站提供公共数据库.

我们只关注插件应该如何工作,而不是它如何处理该功能,或者 如何有效地做到这一点.

从上面看, 很明显,WordPress表现不佳的根本原因是糟糕和低效的代码. 然而, WordPress通过各种api提供了所有必要的功能,这些api可以帮助我们 构建性能更高的插件和主题 不影响整个平台的速度.

聘请Toptal这方面的专家.
现在雇佣
Martín Di Felice

Martín Di Felice

验证专家 在工程
18 的经验

阿根廷布宜诺斯艾利斯省Villa Ballester

2016年4月4日成为会员

作者简介

Martin是一个拥有9年Wordpress和后端开发项目经验的全栈开发人员.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

专业知识

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

Toptal开发者

加入总冠军® 社区.