前几天在 ShopTalk 上,我们遇到的一个问题让我们在 WordPress 插件、它们加载的资源以及在一个理想世界中这些资源会是什么样子等方面进行了一段简短的讨论。我最终 写下了一些想法 并得到了一些反馈。我认为它得出了一个比较令人满意的结论,所以我想把它写出来。
一些插件的工作原理
让我们以一个现实世界的例子为例。 WP-Polls 插件。我认为这是一个不错的插件。在投票方面做得很好。我在 CSS-Tricks 上也使用它。
为了在您的网站上放置这些投票,它需要一些 JavaScript 来处理功能(例如,投票和在不刷新页面的情况下查看结果)以及 CSS 来为投票小部件(结果条等)设置样式。
它添加 CSS 的方法是通过 wp_head()
钩子注入一个样式表,将其放在 <head>
中
<link rel='stylesheet' id='wp-polls-css' href='http://example.com/wp-content/plugins/wp-polls/polls-css.css?ver=2.67' type='text/css' media='all' />
它添加 JavaScript 的方法是通过 wp_footer()
钩子注入一个脚本,将其放在文档底部附近
<script type='text/javascript' src='//example.com/wp-content/plugins/wp-polls/polls-js.js?ver=2.67'></script>
这很有道理。这是他们使此插件正常工作需要做的事情。插件作者需要确保他们的插件易于使用且有效。
作为一名关注性能的开发者,我想合并脚本和样式。
现在,我们在页面上加载了这两个单一用途的资源。当您深入研究 Web 性能以及如何加快网站速度时,您听到的第一个建议之一就是合并资源。一个非常好的经验法则:网站需要加载的资源越少,速度就越快。
合并资源并不是只有最顶尖的网站才需要担心的一些晦涩难懂的事情。这是每个网站都会遇到的问题。人们已经用无数种方法解决了这个问题。CSS 精灵就是关于合并图像资源的。图标字体和 SVG 精灵正在解决同样的问题。CSS 预处理器可以帮助您合并样式表。Rails Asset Pipeline 可以帮助您合并资源。有大量的 Grunt 和 Gulp 插件专为此设计。
但我们在这里处于 WordPress 环境中,所以我们有针对这种情况的解决方案。
插件本身应该提供帮助吗?
我想到的第一个想法是,插件应该允许我们从它们自己添加的 UI 中取消排队任何它们排队的元素。甚至 可以做到 为您提供它们本来要加载的资源,以便您轻松地复制粘贴到自己的系统中。
我现在认为这有点误导。要让 WordPress 插件世界发生这样的转变,需要一场重大的运动。即使真的发生了,那也是很多重复的工作,而且这个问题可以更有效地解决。
解决方案 #1:使用插件
插件 MinQueue 提供了一个我喜欢的解决方案。它不会自动执行任何操作,它允许您配置要合并的资源以及合并顺序。
启用插件后,您将在前端的管理栏中看到一个可以点击的小助手链接。

在我们的演示中,我知道我想将主题的 CSS 和 WP-Polls CSS 合并在一起。因此,我从助手那里获取这些名称,并将它们放入插件设置中的新“队列”中。

现在,这两个 CSS 文件都不会单独加载了。MinQueue 创建了一个组合(并缓存)版本并提供服务
<link rel='stylesheet' id='minqueue-117c22aa-ebc80003-css' href='http://example.com/wp-content/uploads/minqueue-cache/minqueue-117c22aa-ebc80003.css' type='text/css' media='all' />
您可以创建多个“队列”,这为您提供了良好的控制。例如,也许您网站的某个部分加载不同的资源,如果需要,这些资源可以单独合并,您不需要将它们与主组合并。
请注意,这意味着您需要 排队 主题的样式表,但这很容易。
还要注意,流行的 W3 Total Cache 也执行合并,但我发现它有点令人困惑。您通过 URL 添加样式表,它似乎有点过于基础并且容易出错。
解决方案 #2:手动取消排队资源并自行合并
添加资源的插件通过 wp_enqueue_script 和 wp_enqueue style 来实现。您可以深入研究它们的插件代码,找到它们执行此操作的位置,以便您可以查看它们在执行此操作时应用的名称。然后,在您自己的主题的 functions.php 文件(或自定义功能插件)中,您取消排队它们。
Justin Tadlock 有一篇关于这方面的文章,您可以阅读。取消排队一个样式表的简单示例
add_action('wp_print_styles', 'my_deregister_styles', 100);
function my_deregister_styles() {
wp_deregister_style('name-of-style');
}
现在,您需要自己找到该资源并将其合并到您仍在页面上加载的 CSS 中。也许您正在使用 CSS 预处理器,并且您可以 @import 它。也许您正在使用像 Grunt 这样的任务运行程序,并且可以将其添加到要获取和合并的文件列表中。或者完全手动操作,只需将它的内容复制粘贴到您自己的样式表中(只是要注意,如果您这样做,当插件更新时,您将无法获得更新)。
解决方案 #3:使用插件来取消排队资源并自行合并
虽然我能够深入研究插件的代码来查找排队资源的实例,但这对我来说似乎不是一个很棒的方法。我宁愿以编程方式执行此操作,使其更简单并减少人为错误。
在之前围绕此问题进行的讨论中, Nate Wright(来自 Theme of the Crop)为此开发了一个全新的插件,名为 Asset Queue Manager。它有一个用户界面,您可以(从前端)使用它来轻松取消排队资源。
从网站的前端,您可以在管理栏中点击一个链接以显示该页面上所有排队资源的下拉列表。

有一个按钮可以取消排队该资源。该插件将一直保持该资源取消排队,直到您说否则。现在,您需要再次将它合并到您的样式表中,无论您希望如何。那里还有一个按钮直接链接到资源,使其超级容易找到。非常酷!
结论
有很多方法可以控制 WordPress 插件加载的 CSS 和 JavaScript。您可以并且应该这样做,并且随着每个未合并资源的增加,紧迫性也会增加。
每种类型的资源文件可以加载多少个? 一、二或三。
很棒的文章,我真的很喜欢玩 CSS,最近我也在 YouTube 和 Udemy 上学习一些课程,但您在 Css-tricks 上的帖子和文章确实帮助我很多,让我掌握了 Css 和 HTML 技能。
谢谢,继续写作,继续帮助 :)
嗨,Chris。精彩的文章。
所有这些“你应该加快网站速度”的文章,甚至yslow、Google等官方给出的建议,真正让我困扰的是,它们从未考虑到WordPress庞大的安装用户基础,以及我们大多数人根本无法按照它们要求我们必须做到的那样去做。
我们常常无法轻松地获取所有插件并重构代码以减少HTTP请求;我们甚至常常无法阻止这些插件执行它们一半的功能,除非我们拥有比普通静态页面设计师更多的知识。然而,尽管WordPress在全球范围内被广泛使用,但直到最近这个问题才开始得到解决。
我真的不明白为什么花了这么长时间——这意味着大量网站的运行速度远低于它们应该达到的速度,因为没有任何建议和指导容易遵循。我感到困扰的是,很少有人花时间去了解WordPress网站所有者的需求。
所以,感谢你们推动了这一进程并引入了这些插件。这真的很有帮助。
+1 确实如此
一方面,我希望PageSpeed Insights能够考虑它正在分析的网站类型,例如WordPress,以便更好地优化其建议。但另一方面,平台是什么并不重要——PageSpeed的每个建议都是导致网站速度变慢的因素,应该予以解决。
最近的WordCamp SF上的一位演讲者建议WordPress需要更加关注前端性能,我同意他的观点。WordPress开箱即用时速度很慢,开发人员可以实施数十个步骤来加快速度。但WordPress本身可以在核心代码中承担一部分工作,例如,提供内置的压缩和合并选项。
我觉得PageSpeed Insights和Google很有趣的一点是,它们自己的产品(Analytics、Adsense、Google+)并没有遵循PageSpeed的建议!
请忽略我的自动更正生成的错别字,好吗?我的上一行中本意是“introducing”(引入),我太不好意思再回头检查了。此外,我确定我预览了评论,但显然我没有。请不要聘用我做编码服务:-)
不错的文章。我认为这确实是明智的建议,尤其适合管理少量网站的用户,他们能够专注于维护和优化并投入大量时间。
但是,如果您管理大量网站,我建议您不要使用第三方插件来管理其他第三方插件。在更新核心或插件时,您会处于比我更不稳定的境地。
Chris,当您发布关于此问题的推文时,我编写了一个OOP包来解决它。此处解释了它的作用和原因。
除了在PHP中执行此操作外,您还可以通过安装mod_pagespeed在Apache级别执行此操作。这将合并所有资源,并执行性能至上的开发人员想要执行的所有疯狂操作!
我听到的关于mod_pagespeed的全是好话。但我仍然认为,您希望尽可能创建自定义合并的资源,并让它在这些资源的基础上做它认为最好的事情。
例如,您知道主页需要
a.css、b.css、c.css
但子页面需要
a.css、b.css、c.css、d.css
处理此问题的最有效方法是合并a、b和c,并在该子页面上仅加载d。
好吧,也许吧。如果d足够小,它可能只想进入主包。但如果有数十个“d”,也许不行。这些事情需要大脑来解决。
我想尝试的是使用
wp_print_scripts
(和/或wp_footer
)操作,手动遍历$wp_scripts
全局变量,获取所有资源(已按依赖关系排序以正确解析),当然将脚本与样式分开,对本次请求所需的所有文件(基于文件名)进行哈希处理,然后根据需要连接/压缩它们,缓存结果,并打印引用该缓存文件的script
/link
标签。当然还要从$wp_scripts
中删除这些文件。因此,这也可以处理“一次性”或单页脚本,方法是创建一个包含该脚本的新组合文件,或者如果在第一个缓存文件中找不到该文件,则单独包含该文件。
好文章!我见过的另一个解决方案是CloudFlare的CDN提供的Rocket Loader。它需要专业版帐户,因此不是免费的,但在CDN上缓存您的网站时会自动连接js和css资源。
嗨,Chris,很好的思考,我同意现在采取务实的方法处理这个问题是个好主意。我想知道WordPress核心团队是否有可能考虑一下。理想情况下,我们希望所有样式都放在一个文件中,并且如果我们需要调整插件的外观,我们的样式可以优先显示。那么,如果有一种方法可以将样式排队,而不是将它们注入到头部,而是@导入到style.css中呢?然后我们将获得一个文件以及级联的强大功能。
它不会解决始终加载所有样式的问题,但肯定比现状要好。
嗯。
我会喜欢你的文章。
当然,连接很有帮助,这提高了网站的YSLOW评分,使网站加载速度更快。
又一篇很棒的文章!感谢分享MinQueue插件!
像W3 Total Cache这样的缓存插件不是已经这样做了么?它们不会连接和缓存所有js和css文件么?我认为它们会……
我也在使用wp-total cache工具。我对WordPress开发比较陌生,自2011年以来就没有接触过它了。
我担心使用它,因为它是一个巨大的资源,但这是公司想要和需要的。
有人知道其他让WordPress加载速度更快的技巧吗?
确认一下,W3 Total Cache有多种方法可以压缩和合并资源。您可以手动输入URL——这是一种糟糕的做法。但是,如果您仔细查找,会发现一个“帮助”按钮,它会引导您进入一个向导,您只需点击所需的文即可。
它似乎会遍历您所有的主题文件以查找JS或CSS调用,以及查找已排队的任何内容。当它正常工作时——非常棒。
是的,到目前为止它运行良好。
考虑到“Concatenate”(连接)的含义,它是一个很长的词。而且,enqueue和dequeue上多余的“ue”是怎么回事?
好文章!我发现W3 Total Cache易于设置,但连接有点不直观。我确实设法使用它连接了所有插件的CSS和JS文件,但这需要花费时间来试验设置。
好文章。我相信我读到过大多数浏览器一次只能加载6 个HTTP请求(平均而言),除非它们来自不同的服务器。所以我想这些数字将是每个页面最大依赖项加载量的良好目标。是/否?
向Better WordPress Minify致敬。
https://wordpress.org/plugins/bwp-minify/
它不仅可以压缩css/js。您可以根据每个文件指定它压缩的位置(头部/底部)。
您还可以取消排队文件(从插件加载的文件)。所以我想它有点完成了文章中提到的所有内容。
绝对值得一看
我同意Jonny的观点。Better WordPress Minify值得一试,并且比W3 Cache做得更好。
特别是在W3 Cache的JS压缩功能有时会出现错误,它会无缘无故地关闭,或者甚至不允许您保持打开状态。我最近完成了一个网站,它仍然存在这个问题,并且造成了严重的问题。
就在前几天,我在用YSlow测试一个WordPress网站时想到了这个问题,如何尽可能地优化它,因为它加载了22个外部脚本和12个样式表。我的得分是66分,对于一个图片密集型的网站来说还不错,但仍然……考虑过CDN解决方案,但我也会看看这个插件,感谢这篇文章。
这是一个我长期存在的问题,直到现在我一直都是手动完成所有操作。感谢Asset Queue Manager。太棒了!