解决Cloudflare中开启HTML Auto Minify并结合Rocket Loader时DOMContentLoaded事件缺失问题

最近将我的网站DNS解析整体搬迁到了 Cloudflare 上去。Cloudflare 可以对网站进行优化,但是在开启HTML Auto Minify与Rocket Loader时,发现访问网页时DOMContentLoaded事件缺失。下面来分享一下我的解决经历和方案。

Auto Minify 与 Rocket Loader简介

Auto Minify 可以删除网站源代码(包括CSS,Javascript和HTML)中不必要的字符(如空格和注释等),从而压缩其文件大小,减少需要传输给访问者的数据量,进而缩短页面加载时间。

Rocket Loader通过异步加载 JavaScript (网页内嵌的以及第三方脚本)来缩短绘制时间。更多介绍请参见他们的博客

我是怎么发现DOMContentLoaded事件缺失的

众所周知,document.readyState在Chrome中定义为三种状态:

  • 其值为loading时代表网页正在加载。
  • interactive时代表DOM元素可以被访问,但是图像,样式表和框架等资源依然还在加载。
  • complete时代表网页各种资源已经全部加载完成。

loading -> interactive 状态间变化时会触发window的DOMContentLoaded事件,在interactive -> complete 状态间变化时会触发window的load事件。

然而,在同时开启HTML Auto Minify与Rocket Loader后,访问网站我发现原本触发window的DOMContentLoaded事件后定义应该执行的函数都没有执行。首先我排除了是网站代码本身的问题,因为网站在本地运行正常,并且我也通过以下代码确保了在document.readyState为interactivecomplete时直接执行函数:

if (document.readyState === "interactive" ||
    document.readyState === "complete") {
  foo();
} else {
  window.addEventListener("DOMContentLoaded", foo);
}

因而百思不得其解。

然后我通过将以下代码嵌入网页,输出每次状态变化时document.readyState的值:

console.log(document.readyState);
document.onreadystatechange = function () {
  console.log(document.readyState)
}

发现,在开启HTML Auto Minify与Rocket Loader后,document.readyState此时只存在loadingcomplete两个状态了,缺失了interactive状态,并且在loading -> complete变化时只会触发window的load事件,而不会触发DOMContentLoaded事件。

这似乎是Rocket Loader的Bug,也可能是故意为之。

根据Cloudflare给出的Rocket Loader的原理,其会将所有 JavaScript 的加载一直推迟到渲染之后再进行。渲染之后document.readyState应该已经是interactive了,而在执行js代码时,如果同时开启了HTML Auto Minify,通过上述实验发现此时document.readyState被错误设定为了loading (猜测可能是Rocket Loader中某段代码在开始执行js代码时通过代码错误地赋值为了loading;因为Rocket Loader是闭源的,所以这样做的原因不详。当然也有可能是其他原因),因而导致应该直接执行函数的情况下判断失效,仍然在注册DOMContentLoaded事件。

解决方案

既然知道了原因,那么解决方案也很简单,将下述代码添加到所有注册DOMContentLoaded事件代码之前,无须更改原先任何代码即大功告成。

var inCloudFlare = true;
window.addEventListener("DOMContentLoaded", function () {
  inCloudFlare = false;
});
if (document.readyState === "loading") {
  window.addEventListener("load", function () {
    if (inCloudFlare) window.dispatchEvent(new Event("DOMContentLoaded"));
  });
}

此代码判断如果load事件发生后DOMContentLoaded事件还未发生,则由代码手动触发DOMContentLoaded事件,从而将DOMContentLoaded事件等效于load事件。这样做唯一的缺点是在document.readyState为complete时才触发DOMContentLoaded事件,但是这是目前必须的代价。

当然你也可以直接关闭全局的对 HTML 的 Auto Minify,或者对使用DOMContentLoaded事件的HTML页面通过配置 Page Rules 页面规则关闭Auto Minify,实测也能解决问题。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cloudflare 是一个全球分布式的网络服务提供商,它提供了许多网络安全和性能优化的功能。虽然Cloudflare在提供安全和性能方面有着优势,但有也会出现慢的情况。 首先,Cloudflare的慢可能与其服务器负载有关。由于Cloudflare有大量客户,服务器上可能同处理着许多请求,这可能导致一些请求的响应间变长。当然,这也取决于用户所在地区和具体网络连接的质量。 其次,Cloudflare的网络延迟也可能对其速度产生影响。Cloudflare的服务器分布在全球各地,用户连接到离他们物理位置最近的服务器。如果用户与最近的服务器之间的网络连接不稳定或拥挤,可能会导致Cloudflare响应间变慢。 另外,如果用户正在遇到Cloudflare慢的问题,也有可能是因为Cloudflare服务器维护或升级。Cloudflare定期进行服务器维护来提高系统性能和安全性,这可能会导致一段间内的慢速度。 为解决Cloudflare慢的问题,可以尝试以下方法: 1. 更换DNS解析器:使用其他DNS解析器来尝试连接到不同的Cloudflare服务器,以找到相对较快的连接。 2. 优化网络连接:尽量使用稳定的高速互联网连接,并确保所使用网络设备无故障。 3. 清除浏览器缓存:经常清除浏览器缓存和cookie,以确保每次重新连接都能获取最新的响应。 总结而言,虽然Cloudflare在提供网络安全和性能优化方面有很多优势,但用户有也可能会遇到响应较慢的情况。这可能是由于服务器负载、网络延迟或服务器维护所致。通过尝试优化网络连接和更换DNS解析器等方法,可以帮助解决Cloudflare慢的问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值