作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
今天,WordPress功能强大 超过30%的互联网. 它很容易使用,非常受欢迎,而且短期内不会消失.
但是WordPress可能很慢. 那么如何优化它呢?
有很多关于如何调整和优化WordPress的文章. 事实上,WordPress本身提供了一个 健壮的指南 关于WordPress优化.
在很大程度上, 这些文章和教程涵盖了非常基本但有用的概念, 比如使用缓存插件, 与内容交付网络(cdn)集成, 尽量减少请求. 虽然这些建议非常有效,甚至是必要的, 最后, 他们没有解决根本的问题:大多数慢的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 Options API 提供一系列工具,方便地加载或保存数据. 它在处理小块信息时很有用, 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通过各种api提供了所有必要的功能,这些api可以帮助我们 构建性能更高的插件和主题 不影响整个平台的速度.
阿根廷布宜诺斯艾利斯省Villa Ballester
2016年4月4日成为会员
世界级的文章,每周发一次.
世界级的文章,每周发一次.