authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Martín Di Felice
验证专家 在工程
18 的经验

Martin is a full-stack developer with nine years of experience in Wordpress and back-end development projects.

专业知识

分享

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

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

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

在很大程度上, 这些文章和教程涵盖了非常基本但有用的概念, 比如使用缓存插件, 与内容交付网络(cdn)集成, 尽量减少请求. 虽然这些建议非常有效,甚至是必要的, 最后, they don’t address the underlying problem: Most slow WordPress sites are a result of bad or inefficient code.

优化WordPress性能的高级指南

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

因此,本文主要旨在为开发人员提供 WordPress开发公司 with some guidelines that can help them address the underlying causes of many WordPress performance issues.

WordPress provides many performance-oriented features that are often overlooked by developers. 没有利用这些特性的代码会拖慢最简单的任务 , 比如取柱子. 本文详细介绍了四种可能的解决方案, 如何解决WordPress性能缓慢背后的一些潜在问题.

抓取文章

WordPress offers the possibility of f等hing any kind of post from the database. 有三种基本方法:

  • 使用 查询_posts () 功能: 这是一种非常直接的方法,但问题是它覆盖了主要方法 查询,这可能会导致不便. 例如, 这可能是一个问题,如果我们想确定, 在获取帖子后的某个时刻(例如在内部) footer.php),我们正在处理的是哪种页面. 事实上, the official documentation has a note recommending against the use of this function as you will need to call an additional function to restore the original 查询. 此外,替换主查询将对页面加载时间产生负面影响.

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

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

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

限制查询

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

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

WordPress允许我们指定-1作为该参数的可能值, in which case the system will try to f等h all the posts that meet the defined conditions.

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

首先,我们很少能确定只得到一些结果. 即使我们可以, setting no limit will require the database engine to scan the entire database looking for matches.

相反, limiting the results often enables the database engine to only partially scan the data, 这意味着更少的处理时间和更快的响应.

WordPress默认做的另一件事, 哪些会对性能产生负面影响, is that it tries to bring sticky posts and calculate how many rows were found on the 查询.

然而,通常我们并不真的需要这些信息. Adding these two 参数s will disable those features and speed up our 查询:

$查询 = 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 ]
}

但 while this is pretty simple, it’s not optimal because internally it generates a sub查询. 特别是在大型安装中,这可能导致响应缓慢. It’s faster to let that processing be done by the PHP interpreter with some simple modifications:

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 ]
	}
}

我在那里做了什么?

基本上, I took off some work from the database engine and left it instead to the PHP engine, 在内存中做同样的事情, 这样更快.

如何?

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

Since the 查询 may bring us some posts that we do not want as a result, I increased the posts_per_page 参数. That way I ensure that, even if I had had some undesired posts in my response, I would have at least posts_per_page美元 期望职位.

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

避免复杂的参数化

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

虽然这种灵活性是一个强大的功能, it should be used with caution because that parametrization could translate into complex table joins and expensive database operations.

在下一节中, we will outline an elegant way to still achieve similar functionality without compromising performance.

最大限度地利用WordPress选项

WordPress Options API 提供一系列工具,方便地加载或保存数据. 它在处理小块信息时很有用, for which other mechanisms that WordPress offers (like posts or taxonomies) are overly complex.

Wordpress选项优化

例如, if we want to store an authentication key or the background color of our site’s header, 选择是我们所要寻找的.

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

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

考虑, 例如, a site on which we have a carousel displaying breaking news specified in the back-end. 我们的第一反应是使用如下的元键:

/ /函数.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] ?:空;

正如您所看到的,这种方法非常简单,但并不是最优的. It will perform a database 查询 trying to find a post with a specific meta key. 我们可以使用一个选项来实现类似的结果:

/ /函数.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;

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

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

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

但 because we probably want one breaking news post at a time, it should not be a problem.

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

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

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

例如, 突发新闻, 它非常合适,因为我们不想要一个旧的帖子作为突发新闻, and if we leave the task of changing or eliminating that breaking news to the administrator, 他可能会忘记做这件事. 因此,通过两个简单的更改,我们添加了一个截止日期:

/ /函数.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本身就有 对象缓存机制.

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

但, 默认情况下, 缓存不是持久化的, 这意味着它只在单个请求的持续时间内存在. All data is cached in memory, for faster access, but it is only available during that request.

持久缓存说明

Supporting persistent caching requires the installation of a persistent cache plugin.

Some full-page cache plugins come with a persistent cache plugin included (例如 W3 Total Cache), 但其他人则不然, 我们需要单独安装.

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

One might ask: “If this is such a great feature, why doesn’t WordPress enable it 默认情况下”?

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

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

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

如果我们不能正确处理这个问题, our users will complain that they will not see the changes they have made or that their changes took too long to apply.

有时 we are going to find ourselves making tradeoffs between performance and dynamism, 但即使有这些障碍, persistent caching is something that virtually every WordPress installation should take advantage of.

最快的方式

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

Even though those techniques can be used when programming back-end tools or form submissions from the front-end, 如果不是绝对必要的话,应该避免使用.

这样做的原因是为了使用这些机制, 我们有义务向位于。中的某个文件发出post请求 wp-admin 文件夹. 的 majority (if not all) of WordPress full-page caching plugins neither cache post requests nor calls to administrator files.

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

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

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

不要认为WordPress太慢了

的se are just a few pieces of advice that developers should consider when coding for WordPress.

有时, we forget that our plugin or theme might need to live together with other plugins, or that our site may be served by a hosting company that serves hundreds or thousands of other sites with a common database.

We just focus on how the plugin should function and not on how it deals with that functionality, or 如何有效地做到这一点.

从上面看, it is clear that root causes of poor performance in WordPress are bad and inefficient code. 然而, WordPress provides all the necessary functionalities through its various APIs that can help us 构建性能更高的插件和主题 不影响整个平台的速度.

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

Martín Di Felice

验证专家 在工程
18 的经验

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

2016年4月4日成为会员

作者简介

Martin is a full-stack developer with nine years of experience in Wordpress and back-end development projects.

authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.

专业知识

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

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

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

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

Toptal开发者

加入总冠军® 社区.