Contents
前言
本来这周的文章不是写这个,不过,因为群里的一个小伙伴提到了使用instant.page来优化wordpress的访问,我发现居然没听说过这个东东(我承认自己孤陋寡闻了,毕竟是才接触wordpress一年出头的新人~),然后查了一下,发现工作原理蛮有意思的,想到我也好久没有在优化博客方面下过功夫了,所以就装上试试,然后想到既然都用了,干脆这周就写这个算了~。
常规优化wordpress访问速度的方式
对于使用wordpress搭建网站的朋友来说,”优化wordpress的访问速度”是个无法回避的挑战,一般来说,常规的优化方法有下列选择:
1. WordPress本地层面的优化选择
缓存插件(如 WP Super Cache)
• 静态页面缓存:通过将动态生成的页面缓存为静态HTML文件,减少页面加载时间。启用预加载功能,可以在用户访问之前提前生成并缓存常访问页面。
• 浏览器缓存:设置适当的浏览器缓存头,确保静态资源(如CSS、JS、图片)在访问者的浏览器中缓存,减少重复加载。
Redis数据库缓存
• Redis 缓存和对象缓存:通过使用 Redis(如 Redis Object Cache 插件),缓存 WordPress 的数据库查询结果、评论、登录状态等动态内容,减少数据库访问频率,提升数据检索速度,并优化整体性能。
• 持久化缓存策略:配置 Redis 保留缓存的有效期和过期策略,确保缓存既能提升性能,又不至于过期过快。
图片和媒体优化
• 图片Lazy Loading(延迟加载):使用插件(如 WP Rocket 或 LazyLoad)启用延迟加载,优先加载用户可见区域的内容,其余图片只在进入访客可见区域时才加载,减少初始加载时间(该功能从wordpress 5.5版本就默认启用)。
• 图像优化:通过插件(如 ShortPixel、Smush)或手动方式压缩图像,减小图片体积,提高加载速度。
• WebP格式:使用 WebP 格式替代传统的 JPEG/PNG 格式,提供更小的文件体积。
数据库优化
• 定期优化数据库:使用插件(如 WP-Optimize)定期清理无用数据(如修订版本、垃圾评论等),保持数据库整洁,减少查询时间。
• 减少不必要的查询:精简 WordPress 的查询,避免插件或主题导致的高频次数据库访问。
精简插件和主题
• 禁用不必要的插件,减少插件对性能的影响。选择轻量级且优化良好的插件,避免使用过于复杂或不常更新的插件。
• 选择高性能、优化良好的主题,避免使用过多的 JavaScript 和 CSS,保持主题代码简洁。
2. CDN 层面的优化选择(以cloudflare为例)
缓存规则
• 静态资源缓存:通过配置 CDN(如 Cloudflare)的缓存规则,将 WordPress 网站的静态资源(如 CSS、JS、图像等)缓存到 CDN 节点。这样可以减少回源请求,加快静态资源的加载速度,从而提高整体访问速度。
• 全页面缓存:将 WordPress 页面通过 CDN 全页面缓存,将整个页面的内容(除了部分不能缓存的内容)缓存到 CDN 节点,减少服务器的负担,并显著降低响应时间。尤其适用于不频繁变动的页面,例如文章页面、静态页面等。
• 缓存策略与细化控制:根据内容的更新频率,合理设置不同的缓存策略。对于变化较少的静态资源(如图片、CSS 文件、JavaScript 文件等),可以设置较长的缓存时间;而对于频繁变动的内容(如带有用户个性化信息的页面、用户面板等),则应避免缓存或设置较短的缓存时间,确保内容的及时更新和准确性。需要特别注意的是,评论等动态内容通常不适合缓存,因为这些内容会随着用户的互动而变化,必须确保其动态生成。
• 边缘缓存 (Edge Cache):通过利用 CDN 提供的边缘缓存,缓存用户离节点最近的数据,提高加载速度。边缘缓存通过减少源站的负载和响应时间,提高网站访问的稳定性和速度。通过设置 TTL(缓存存活时间),可以灵活控制缓存刷新频率,确保缓存数据的时效性。
Worker相关的优化方式
• Cloudflare Workers:Cloudflare Workers 是边缘计算功能,允许开发者在 CDN 边缘节点上执行自定义的缓存逻辑。通过 Workers,你可以根据用户的地理位置、设备类型、请求语言等因素,灵活地调整缓存策略。例如,可以根据不同用户的请求条件缓存不同版本的页面,或者根据实时数据决定是否缓存某个请求。Workers 提供了更细粒度的缓存控制,适合高度定制化的场景。
• APO(Automatic Platform Optimization):APO 是 Cloudflare 为 WordPress 优化的专用服务,它通过自动缓存 WordPress 的页面(包括动态内容),并通过 Cloudflare 的全球 CDN 网络加速这些页面的加载。APO 自动处理常见的缓存规则,减少了对源站的请求,并提升页面的加载速度。APO 非常适合大多数 WordPress 网站,特别是那些需要高并发处理的站点。
以上这些是常规的wordpress优化加速的方法,不过,这几天又知道了一种优化方法:instant.page,使用的是”预加载”的方式(感谢小伙伴”tony8077616″的推荐),该方式是从另一个层面”提升”访客访问wordpress网站时打开页面的速度,我测试之后觉得挺有效,所以专门用本文来记录一下。
instant.page和”预加载”
什么是”预加载”?
其实,instant.page(官方网址:https://instant.page/)的”预加载”和上一节”图片和媒体优化”部分提到的”延迟加载”类似,都可以算是“欺骗”用户感觉提升用户”感知加载速度”的”障眼法”:它通过利用”鼠标悬停到点击之间的时间”进行预加载,让页面内容在用户点击时几乎即时展现,从而”欺骗大脑”(人的大脑将耗时小于 100 毫秒的动作视为即时操作),让用户感到页面加载更快,但实际的网络加载速度并未改变。
一般正常人点击一次链接的时间大概为300多毫秒:
所以理论上来说,”预加载”方式至少能省300多毫秒。
技术原理
instant.page其实只是一段独立的 JavaScript 代码,其主要功能是监听用户的鼠标悬停事件,提前加载目标页面内容,从而显著缩短用户点击后页面加载的等待时间。它无需依赖任何特定的平台或 CMS,而是基于网页的通用交互行为(如鼠标悬停)进行优化。在触摸屏设备上,这一过程对应的是从用户触摸链接开始,到手指离开屏幕之间的时间段,其技术原理如下:
- 监听鼠标悬停事件:当用户将鼠标悬停在某个链接上时,instant.page 会捕捉到这个行为。
- 预加载目标页面:instant.page 会使用 fetch() 请求,提前加载鼠标悬停的链接对应的目标页面的资源(如 HTML、CSS、JavaScript 等)。
- 提前准备内容:这些预加载的资源会被浏览器缓存或存储在内存中,以便用户点击链接时,页面几乎即时显示。
instant.page和常规优化方式的关系
Instant.page虽然是一种基于用户行为预加载页面资源的工具,然而,它并非一个独立的性能优化手段,而是依赖于之前提到的WordPress 传统优化方式,只有先完成这些传统优化,Instant.page 才能真正发挥其优势,举例如下:
1. wordpress本地层面的优化与 Instant.page 的协同
静态页面缓存与浏览器缓存
• Instant.page 的依赖:当用户在浏览某页面时,Instant.page 会通过预加载将目标链接的静态 HTML 文件加载到浏览器。如果静态页面缓存已启用(如 WP Super Cache 提供的功能),Instant.page 可以直接加载已缓存的静态页面,而不是请求动态生成的页面,从而大幅减少服务器负载和响应时间。
• 作用增强:浏览器缓存设置得当时,Instant.page 的预加载请求会从用户浏览器缓存中获取 CSS、JS 等静态资源,而不需要从服务器或 CDN 加载。这进一步加快了页面加载速度。
Redis 数据库缓存
• Instant.page 的依赖:Instant.page 不能直接优化 WordPress 的动态查询,但如果 Redis 已经缓存了数据库查询结果,则 Instant.page 的预加载请求会触发 Redis 的快速响应,而非直接访问数据库。
• 作用增强:通过 Redis 提供的对象缓存,动态内容(如评论或登录状态)也可以被快速响应,避免 Instant.page 的预加载引发数据库性能瓶颈。
图片与媒体优化
• Instant.page 的依赖:Instant.page 预加载时会触发图片资源加载。如果已启用延迟加载(Lazy Loading),且使用了优化的图片格式(如 WebP),预加载的图片资源会更小更快。
• 作用增强:通过 ShortPixel 或 Smush 等插件压缩图片,Instant.page 的预加载请求会占用更少的带宽,并提升加载速度。
2. CDN 层面的优化与 Instant.page 的协同
CDN 是提升 WordPress 网站性能的重要工具,其缓存能力和边缘计算支持能显著降低回源压力,加速页面加载。而 Instant.page 的预加载功能可以充分利用 CDN 的优势,在资源已被缓存的情况下直接从 CDN 节点读取,进一步提升访问速度。
静态资源缓存
• Instant.page 的依赖:通过 Cloudflare 等 CDN,将静态资源(如 CSS、JS、图片等)缓存到离用户最近的 CDN 节点。Instant.page 的预加载请求会优先从这些节点获取资源,减少延迟。
• 作用增强:合理设置静态资源的缓存策略(如长时间缓存不常变动的资源),Instant.page 的预加载可以快速响应,显著减少服务器负载和网络延迟。
全页面缓存
• Instant.page 的依赖:CDN 的全页面缓存功能(如 Cloudflare 的 APO)会将整个页面缓存到边缘节点。Instant.page 的预加载请求在这种情况下无需服务器生成页面内容,而是直接加载缓存的 HTML 页面。
• 作用增强:对于文章页或其他更新频率较低的内容,全页面缓存可与 Instant.page 配合,实现接近瞬间的加载速度。
边缘缓存与边缘计算
• Instant.page 的依赖:通过边缘缓存(Edge Cache),CDN 可将用户最近访问的内容缓存到靠近用户的节点。Instant.page 的预加载会直接从边缘节点加载资源,而无需回源服务器。
• 作用增强:利用 Cloudflare Workers 等边缘计算工具,可以实现更灵活的缓存控制。例如,根据用户设备、地理位置或语言加载特定资源,Instant.page 的预加载功能可以触发这些针对性优化。
Cloudflare Workers 与定制优化
• Instant.page 的依赖:Cloudflare Workers 允许在边缘节点上运行自定义逻辑。例如,动态生成不同版本的页面缓存或处理特殊请求条件,Instant.page 的预加载可以直接与这些自定义缓存逻辑配合。
• 作用增强:通过 Workers,预加载可以为不同用户请求提供高度个性化的内容,进一步提升加载速度和用户体验。
APO(Automatic Platform Optimization)
• Instant.page 的依赖:Cloudflare 的 APO 专为 WordPress 优化,通过自动缓存页面和静态资源,减轻服务器负担。Instant.page 的预加载与 APO 完美集成,能够直接加载优化过的内容。
• 作用增强:特别是在高并发场景下,APO 提供了稳定的缓存响应能力,确保 Instant.page 的预加载不会因服务器压力或动态生成瓶颈而失效。
动态内容的缓存细化
• Instant.page 的依赖:对于动态内容(如评论、用户面板等),缓存策略的细化至关重要。例如,使用 Workers 或其他工具动态生成不可缓存部分的内容,Instant.page 的预加载请求可以触发精确控制的动态加载逻辑。
• 作用增强:这种优化可以兼顾动态内容的实时性和静态内容的加载速度,使 Instant.page 的预加载兼容复杂场景。
总的来说,CDN 的缓存与优化功能为 Instant.page 提供了坚实的基础支持:通过合理配置静态资源缓存、全页面缓存、边缘缓存,以及利用 Workers 和 APO 等高级功能,Instant.page 的预加载能更高效地响应用户请求,并显著降低服务器压力。更重要的是,这些优化措施的协同作用,使 Instant.page 的加速效果最大化,让用户体验真正实现“所点即现”。
部署instant.page
前面讲原理,啰啰嗦嗦讲了一大堆,但是实际部署instant.page的时候却非常简单,因为其本质上就是一段js代码而已,而部署这段代码的方式却可以有多种方式。
在wordpress上部署
使用插件的方式
如果是在wordpress上部署,最简单的方式是使用插件的方式,只需要直接安装instant.page的插件即可:
安好好插件直接启用即可,无需额外的设置:
直接引用官方提供的的脚本地址
只需要将如下代码:
<script src="//instant.page/5.2.0" type="module" integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script>
插入wordpress的footer.php文件的</body>
之前即可(常规的HTML静态也面可以直接插入</body>
之前)。
注:这种方式需要客户浏览器能够正常加载https://instant.page/5.2.0
这个官方提供的脚本地址。
加载本地的js脚本
这种方式需要先把”instantpage.js”脚本放到本地wordpress的路径中,推荐放到wp-content 的子目录中,例如:
wp-content/js/instantpage.js
然后和前面一样,在footer.php文件中的/<body>
之前插入如下代码即可:
<script src="/wp-content/js/instantpage.js" type="module"></script>
关于instantpage.js文件,可以在github的instant.page的主页上(instant.page github主页)去看脚本的最新版内容,或者直接从官网提供的地址获取(https://instant.page/5.2.0
):
不过github上的版本要新一些,要使用的话尽量用github上的版本吧。不方便访问github的朋友,也可以从我的”博客文件分享专用链接”中进行下载(https://fileshare.tangwudi.com/s/file,分享密码:blog.tangwudi.com),如下图:
高端版:基于cloudflare worker的方式
这种方式不仅可以让你无需在wordpress搭建的网站中安装插件(或者footer.phpo文件中直接引入 instant.page 的脚本,还能更高效地利用 Cloudflare 的全球边缘网络分发和执行脚本,如果你的网站使用的是动态生成的 HTML 页面(例如 WordPress),此方式特别适用。具体创建worker的步骤可以参考文章:家庭数据中心系列 cloudflare教程(七) CF worker功能介绍及基于worker实现”乞丐版APO for WordPress”功能加速网站访问的实操、验证及相关技术原理研究。
worker脚本的内容如下:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
// 检查是否为 HTML 页面
if (url.pathname.endsWith('.html') || url.pathname === '/') {
const response = await fetch(request);
const contentType = response.headers.get('content-type') || '';
// 只对 HTML 类型的响应注入 instant.page 脚本
if (contentType.includes('text/html')) {
const text = await response.text();
const modifiedBody = text.replace(
'</body>',
`<script src="//instant.page/5.2.0" type="module" defer integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script></body>`
);
return new Response(modifiedBody, {
headers: response.headers,
status: response.status,
statusText: response.statusText,
});
}
}
// 对非 HTML 请求保持原样
return fetch(request);
}
如果要验证worker方式是否成功,可以使用浏览器的开发者工具,查看站点的HTML 页面源代码,确认<script src="https://instant.page/5.2.0"...>
是否已被正确注入到 <body>
标签末尾,如果是,则说明配置成功。
注1:保留 //instant.page 中的双斜杠以支持协议相对加载,从而自动适应 http 或 https。
注2:如果未来需要使用其他版本,只需更新版本号和对应的 integrity 值即可。
注3:由于Cloudflare Workers 在流量序列中的优先级较低,仅在其他功能模块未对请求处理或拦截时才会生效。因此,为了确保 Worker 的脚本可以正常运行,并实现预期效果,请合理配置优先级较高的功能模块,例如”页面规则”、”缓存规则” 或者WAF等。关于”流量序列”的具体细节请参考文章:家庭数据中心系列 cloudflare教程(二) CF整体方案流量序列中各技术节点功能简介。
注4:使用 Cloudflare Workers可能涉及额外费用(免费计划每天有100,000 次请求的限制,超过之后默认行为是拒绝访问,当然也可以改为超过限制后直接回源~),请根据网站实际的访问率进行评估。
验证instant.page的”预加载”效果
要想验证instant.page的”预加载”是否生效很容易,只需要使用浏览器的开发者工具即可。
首先找一个页面,比如我就使用我博客的”AI学习地图”:
上图红框中的链接就当做测试链接,然后打开浏览器的开发者工具(我使用的是chrome):
然后从上到下依次把鼠标从6篇文章的链接上划过,然后观察右边开发者工具中记录的网络日志:
可以看到”预加载”效果是生效了的。
除了”欺骗”,是否还有”真情”?
预加载也能缩短页面整体加载时间
虽然”预加载”可以通过”欺骗”访客大脑的方式来让访客认为访问速度得到提升,但是,是否真的对缩短整个页面的实际加载时间毫无帮助呢?
其实,Instant.page 可以在某些情况下实际缩短网页加载时间,而不仅仅是”欺骗”访客大脑。虽然它的核心机制”预加载”目的在于改善用户体验,给人一种”更快”的感觉,但这并不意味着它在任何场景下都对实际加载时间毫无影响。以下是它可以帮助缩短加载时间的几种情况:
1. 缓解网络延迟 (Latency Reduction)
Instant.page 的预加载机制会在用户将鼠标悬停在链接上时,主动加载目标页面的资源。因为加载资源的请求是提前发出的,它能够显著减少点击链接后用户等待服务器响应的时间。
• 适用场景:高延迟网络环境下,服务器响应较慢的网站。
• 实际效果:用户点击链接时,目标页面的资源可能已经加载完毕或部分加载完成,从而减少了后续加载所需的时间。
2. 充分利用带宽空闲时间
在用户尚未点击链接的短时间内(如鼠标悬停或触摸屏用户短暂停留),网络通常处于空闲状态。Instant.page 会利用这一空闲时间发送预加载请求。
• 适用场景:带宽充足的网络环境。
• 实际效果:这些资源在用户点击链接之前已经加载或缓存,页面加载时无需重复请求,实际加速了页面加载。
3. 与缓存机制的结合
Instant.page 的预加载机制可以更好地与缓存策略(如 CDN 和浏览器缓存)配合,提前加载资源,从而提升页面的加载体验。
• CDN 缓存:当目标页面的资源已经被缓存到 CDN 节点,Instant.page 的预加载请求同样会直接从 CDN 获取资源,从而避免不必要的回源请求。虽然这与直接点击请求资源的行为没有本质差别,但预加载通过提前触发请求,使得资源加载可以更早完成。
• 浏览器缓存:Instant.page 的预加载请求会将目标资源存储到浏览器缓存中。当用户正式访问页面时,浏览器可以直接调用缓存的资源,避免重新发起请求,从而减少加载时间。
• 适用场景:网站已启用了有效的缓存策略(如静态资源的长期缓存规则);资源通过 CDN 分发,且用户的网络与 CDN 节点之间具有较低的延迟。
• 实际效果:Instant.page 提前完成资源的加载或部分加载,缩短了用户点击后的加载时间;浏览器缓存机制进一步减少了重复请求,优化了页面的加载效率。
4. 动态内容的快速预生成
对于动态内容(如个性化页面),如果网站配合服务器端技术(如 Redis 缓存或 Cloudflare Workers)在用户预加载时触发内容生成,Instant.page 可以间接优化页面的生成时间。
• 适用场景:动态页面加载需要生成内容的网站。
• 实际效果:在用户正式请求页面之前,动态内容已经生成好并可快速响应。
5. 减少首次字节时间(Time to First Byte, TTFB)
通过 Instant.page 的提前请求,浏览器和服务器可以提前完成 TCP 连接的建立、SSL 握手以及初始资源获取,从而缩短页面的 TTFB。
• 适用场景:TTFB 较长的网站。
• 实际效果:首次字节时间的缩短直接减少了总加载时间。
6. 提升首屏加载速度
Instant.page 重点预加载目标页面的关键资源(如 HTML 文件),这使得用户进入新页面时,首屏内容可以更快地呈现。
• 适用场景:首屏渲染时间对用户体验要求较高的网站。
• 实际效果:即便非关键资源仍需加载,用户感知的首屏呈现速度更快,实际页面加载时间也因此缩短。
综上所述,尽管 Instant.page 的机制是以”欺骗”访客大脑的方式提升感知速度,但它并非完全无法缩短实际加载时间。在特定场景下,它通过以下方式对网页加载时间产生实际影响:
• 提前发起资源请求,减少延迟。
• 利用空闲带宽提升资源加载效率。
• 配合缓存策略或动态生成机制优化加载性能。
不过,这些效果的发挥高度依赖网站的基础优化(如缓存策略、CDN 部署等)。如果网站优化不到位(例如没有 CDN 或缓存策略),Instant.page 的实际帮助会大打折扣,更多地停留在“感知速度提升”层面。
如何验证上述结论?
本来,我想用谷歌网站测速”PageSpeed Insights”来验证上一节内容得出的结论:既instant.page能够在特定场景下缩短实际加载时间。但是关键问题在于,就算我正常的连续2次使用”PageSpeed Insights”进行测试,分数结果可能也会差别很大,比如这次的测试结果:
第一次:
第二次:
所以没法直接从分数上直接来看效果,看来要着落在:First Contentful Paint(FCP)、Largest Contentful Paint(LCP)、Total Blocking Time、Cumulative Layout Shift(CLS) 、Speed Index这5个关键参数的数值变化上了。
不过,理论上来说,instant.page的”预加载”并不是对每一个参数都有效,所以需要先从理论上梳理一下预加载对各个参数的影响:
1. First Contentful Paint(FCP)
• 定义:页面首次渲染可见内容的时间。
• instant.page 的影响:显著优化。预加载提前获取了关键资源(如 HTML、CSS),使页面可以更快开始渲染内容。
2. Largest Contentful Paint(LCP)
• 定义:页面最大可见内容的渲染时间。
• instant.page 的影响:显著优化。关键资源(如图片或主文本块)提前加载,减少等待时间,从而缩短 LCP。
3. Total Blocking Time(TBT)
• 定义:主线程被长任务阻塞的总时间。
• instant.page 的影响:无明显影响。预加载机制不会减少 JavaScript 的解析和执行时间,但资源提前加载可能间接减少部分与资源加载相关的阻塞。
4. Cumulative Layout Shift(CLS)
• 定义:页面加载过程中布局的稳定性。
• instant.page 的影响:无明显影响。预加载不会直接干预布局变化,但如果资源提前加载完成(如字体或图片),可能间接减少因资源加载延迟导致的布局抖动。
5. Speed Index
• 定义:页面加载过程中可见内容显示的速度。
• instant.page 的影响:显著优化。预加载资源使页面能更快显示可见内容,从而提升 Speed Index。
性能指标 | instant.page 的优化效果 |
影响分析 |
---|---|---|
First Contentful Paint(FCP) | 显著优化 | 提前加载资源,加快首个内容渲染时间。 |
Largest Contentful Paint(LCP) | 显著优化 | 关键资源提前加载,使最大内容块更快渲染。 |
Total Blocking Time(TBT) | 无明显影响 | 不干预主线程任务,仅间接减少部分资源加载导致的阻塞。 |
Cumulative Layout Shift(CLS) | 无明显影响 | 与布局变化关系较弱,但间接减少部分资源延迟引起的抖动。 |
Speed Index | 显著优化 | 资源预加载提升了页面显示的连贯性和速度。 |
注意事项:
1. FCP 和 LCP 是 instant.page 影响最大的指标,适用于需要加快首屏和主内容加载的场景。
2. 如果需要优化 TBT 和 CLS,需要结合其他手段(如优化 JavaScript 和避免布局抖动)。
实际验证
注:为了做这个实验,我要先禁用instant.page插件,然后清除cloudflare上的所有缓存,之后运行一次”PageSpeed Insights”;然后启用instant.page,又要清除cloudflare上的所有缓存,再运行一次”PageSpeed Insights”,为了科学,我牺牲好大~。
禁用instant.page的结果:
启用instant.page的结果:
这个嘛,感觉差异都在合理的误差范围之内呀,看来,本次测试的结果并不能验证上一节的结论,实验失败,感觉是因为使用了cloudflare的CDN之后,测试过程中又多了很多额外的因素,如果没有CDN应该会比较直观,不过,我实在是没有精神再折腾了~。
“注销”、”退出”按钮的特殊处理
采用instant.page实现预加载功能之后,有一个问题,就是鼠标划过”注销”、”退出”按钮时就直接执行了,这时候登录用户本身可能还未意识到这个问题,执行一些需要登录的操作就会报错。
那么,在WordPress中如何优化这个问题呢?以下是优化方法的几种思路供大家参考:
1. 排除敏感链接的预加载
方法:利用 data-no-instant 属性
在 WordPress 中,“注销” 和其他敏感链接通常由主题或插件生成。可以通过以下方式添加 data-no-instant:
a. 修改主题模板文件
找到生成这些链接的模板代码(如 wp_nav_menu() 或其他生成菜单的代码),并手动添加 data-no-instant。
示例代码:
<?php
wp_nav_menu(array(
'theme_location' => 'primary',
'items_wrap' => '<ul id="%1s" class="%2s">%3s</ul>',
'walker' => new class extends Walker_Nav_Menu {
public function start_el(&output, item,depth = 0, args = null,id = 0) {
output .= sprintf(
'<li><a href="%s"%s>%s</a></li>',
esc_url(item->url),
(strpos(item->url, '/logout') !== false) ? ' data-no-instant' : '',
esc_html(item->title)
);
}
}
));
?>
b. 通过 WordPress 钩子动态添加
如果使用默认的菜单生成函数,可以通过 wp_nav_menu_items 或 wp_get_nav_menu_items 钩子动态修改链接属性:
add_filter('wp_nav_menu_items', function(items) {
return preg_replace('/href=["\'](.*logout.*)["\']/', 'href="1" data-no-instant', $items);
});
2. 利用 JavaScript 动态阻止
在 WordPress 中,您可以将这部分逻辑写入主题的自定义 JavaScript 文件或通过插件添加。例如:
方法:通过 wp_enqueue_script 添加脚本
add_action('wp_enqueue_scripts', function() {
wp_enqueue_script('disable-preload', get_template_directory_uri() . '/js/disable-preload.js', [], null, true);
});
disable-preload.js 示例内容:
document.querySelectorAll('a[href*="logout"]').forEach(link => {
link.setAttribute('data-no-instant', '');
});
3. 使用 JavaScript 验证行为
在 WordPress 中,可以为敏感链接(如 “注销”)添加确认弹窗或额外验证。这适用于通过插件或主题生成的按钮或链接。
方法:添加确认弹窗
在模板文件中,为特定链接添加 onclick 属性:
<a href="<?php echo wp_logout_url(); ?>" onclick="return confirm('确定要注销吗?');">注销</a>
或者通过全局脚本动态添加:
document.querySelectorAll('a[href*="logout"]').forEach(link => {
link.addEventListener('click', function(e) {
if (!confirm('确定要注销吗?')) {
e.preventDefault();
}
});
});
4. 后端逻辑优化
WordPress 提供了丰富的过滤器和动作,可以在后端拦截请求。例如:
方法:判断预加载请求
可以通过 PHP 检测预加载的请求头(如 X-Instant-Page),并避免执行敏感操作。
add_action('wp_logout', function() {
if (!empty($_SERVER['HTTP_X_INSTANT_PAGE'])) {
wp_die('此操作无法通过预加载完成,请重新点击注销按钮。');
}
});
5. 配置 Instant.page 选项
在 WordPress 中,您可以通过以下方式更细粒度地控制 Instant.page 的行为:
方法:配置加载参数
将 Instant.page 脚本加入主题或插件,并设置参数:
add_action('wp_enqueue_scripts', function() {
wp_enqueue_script('instantpage', 'https://cdn.instant.page/5.1.0', [], null, true);
wp_add_inline_script('instantpage', '{mousedown: true, mouseover: 200}');
});
以上这些操作可以有效避免短暂悬停时就触发预加载,大家可以根据自己的实际情况选择最适合自己的优化方式。
注:感谢小伙伴”秋风于渭水”在评论区的提醒。
后话
原本想水一篇文章随便混一周,没想到又折腾了一圈。不过,从wordpress优化的角度来说,我觉得instant.page还是很值得我折腾的,毕竟是从另一个层面来优化wordpress的访问体验,还是蛮有趣的,关键是部署又简单,几行代码或者一个插件的事,推荐使用wordpress的朋友都试试。
顺带提一嘴如果想要自行实现,请一定把【注销】【退出】等链接给排除了,不然会出现鼠标不小心划过【退出登录】按钮,WP登录状态就无了。曾经因此有过非常惨痛的排障过程,找了一大圈才发现是预加载的锅。
感谢,这提醒很重要,回头我补充到文章里去,我博客目前禁用了注册,到是不会遇到这问题,但是其他允许注册博客的博主的确需要重视这问题。