先说结果:
- 我的一个 WordPress 站开着 Cloudflare 的 Rocket Loader。查页面源码,有 19 到 20 个
<script>的 type 被改成了type="一串哈希-text/javascript",浏览器解析 HTML 时会跳过它们,等 Rocket Loader 自己的脚本加载完再按顺序执行。 - 影响最大的是一段手机端的排版脚本:它要把目录和封面挪到正确的位置。被推迟以后,网速慢的手机上,页面会先按原样显示,过一会儿目录和封面才挪过去,页面会跳一下。
- 给这段脚本加上
data-cfasync="false",Rocket Loader 就不再碰它。14 篇文章复验,脚本都在解析时执行,CLS 都是 0。 - 后来把别的脚本都整理好(统计脚本挪到页面加载完以后、去掉用不上的脚本),Rocket Loader 已经没什么可推迟的,它自己反而要占 0.5 到 0.6 秒 CPU(手机仿真),就在 Cloudflare 里直接关了。
- 关掉以后有一个坑:
<head>里的 jQuery 以前一直被它推迟,关掉后变成了阻塞渲染,要自己挪到页脚。
一、先确认 Rocket Loader 有没有改你的脚本
不用登录 Cloudflare,看页面源码就知道:
curl -s https://example.com/ | grep -c 'rocket-loader'
curl -s https://example.com/ | grep -o 'type="[0-9a-f]\{20,\}-text/javascript"' | wc -l
第一条大于 0,说明页面里加载了 rocket-loader.min.js;第二条是被改写的脚本数量。我那个站当时第二条是 19 到 20。
被改写的脚本长这样:
<script type="4f2a…c1-text/javascript">
var mq = window.matchMedia('(max-width: 768px)');
…
</script>
浏览器不认识这个 type,就不会执行。Rocket Loader 等页面解析完,再把这些脚本一个个拿出来执行。
二、哪些脚本不该被推迟
大多数脚本晚一点执行没关系,比如统计、评论、分享按钮。但有一类脚本,晚了用户能看到:
- 改页面结构的脚本:挪元素、加类名、改布局。我那段手机目录脚本就是这种,它在页面显示出来之后才运行,目录和封面就会在用户眼前挪位置。
- 首屏就要用的脚本:吸顶导航、首屏的切换组件。
- 别的脚本要依赖它的脚本。
实验室里测 CLS 是 0,因为本机网速快,脚本推迟得不多。真机上网速慢的时候,推迟的时间会长很多,跳动就看得出来。所以我没等它出问题,按「改结构的脚本不能被推迟」处理。
三、data-cfasync="false" 加在哪
内联脚本,直接写在 <script> 上:
<script data-cfasync="false">
var mq = window.matchMedia('(max-width: 768px)');
…
</script>
外链脚本,Cloudflare 文档要求写在 src 前面:
<script data-cfasync="false" src="/js/app.js"></script>
文档里还有两条要注意:
- 被排除的脚本如果依赖别的脚本(比如依赖 jQuery),被依赖的那些也要加
data-cfasync="false",不然执行顺序会乱。 - 在 JavaScript 里动态加这个属性没用,必须写在 HTML 里。
WordPress 里,用 wp_enqueue_script 加载的外链脚本可以用 script_loader_tag 过滤器统一加。属性插在 <script 后面,自然就在 src 前面:
add_filter('script_loader_tag', function ($tag, $handle) {
if (in_array($handle, ['my-layout-js'], true)) {
$tag = str_replace('<script ', '<script data-cfasync="false" ', $tag);
}
return $tag;
}, 10, 2);
my-layout-js 换成你自己脚本的 handle。自己在主题或插件里手写的内联脚本,直接在标签上加。
加完验证:清一次 Cloudflare 缓存,再跑第一步的 grep,看那段脚本的 type 是不是没被改写了。我当时 14 篇文章逐篇查了,目录脚本都带着 data-cfasync="false",没有被改写。
四、什么时候干脆关掉
Rocket Loader 本身也是一个脚本,要下载、要执行。手机仿真下,我那个站上它自己就占 0.5 到 0.6 秒 CPU。
它值不值,看页面上还有多少「该推迟又没推迟」的脚本。我把下面几件事做完以后,再看就没剩什么了:
- 统计脚本改成页面加载完、浏览器空闲时再载入(自己加
data-cfasync="false",免得 Rocket Loader 再动它)。 - 去掉用不上的脚本:WordPress 自带的 emoji 脚本、jquery-migrate、主题里重复的平滑滚动。
- 剩下的脚本都在页面底部。
这时候就可以关了。位置在 Cloudflare 后台:速度 → 优化 → 内容优化 → Rocket Loader。只有个别页面出问题的话,也可以用 Configuration Rule 按网址单独关。
关之前列一张功能清单,关完逐项点一遍。我那次列的是:
- 页头吸顶(往下滚藏起,往回滚出现)
- 手机菜单打开、关闭
- 搜索打开、关闭
- 首页的切换组件
- 文章页手机目录展开、收起、跳转
- 表格横向滑动提示
- 订阅表单(含 Turnstile 验证)
- 页脚
全部正常,控制台没有新的报错。页面里 rocket-loader.min.js 没有了,原来 20 个被改写的 type 也都没了。任何一项坏了,就先把 Rocket Loader 打开,再查是哪段脚本依赖了它的推迟。
五、关掉以后:jQuery 卡住了首屏
关掉以后,文章页首屏反而没变快。Lighthouse 提示 <head> 里的 jquery.min.js(约 30KB)阻塞渲染。以前它也在 <head> 里,只是被 Rocket Loader 推迟了,所以一直没暴露。
我先确认了 head 和 body 里的内联脚本都不依赖 jQuery,用到 jQuery 的只有一个目录插件,它的脚本本来就在页脚。然后把 jQuery 挪到页脚:
add_action('wp_enqueue_scripts', function () {
if (is_admin()) return;
$s = wp_scripts();
foreach (['jquery', 'jquery-core'] as $h) $s->add_data($h, 'group', 1);
}, 100);
改完 49 篇文章的 <head> 里都没有 jQuery 了,页脚里 jQuery 排在目录插件前面,目录正常。
如果你的主题或插件有在 <head> 里直接写 jQuery(...) 的内联脚本,这样挪会报 jQuery is not defined,挪之前先搜一下。
顺带说一句:那次首屏慢,jQuery 只是其中一部分。我一开始以为全是它,挪完再测,大头在别处(手机端为了不跳动,正文先隐藏、等排版脚本挪完再显示)。这是另一个问题,跟 Rocket Loader 无关,就不展开了。
记下来的几件事
- 源码里看到
一串哈希-text/javascript,就是 Rocket Loader 在推迟这个脚本。 - 改页面结构的脚本、首屏要用的脚本,加
data-cfasync="false"。外链脚本写在src前面,它依赖的脚本也要加。 - 脚本都整理好以后,Rocket Loader 可以直接关。关之前列功能清单,关之后逐项点。
- 关掉以后查一下
<head>里有没有以前被它藏起来的阻塞脚本,最常见的是 jQuery。
同样是 Cloudflare 上踩过的坑,另外两篇:Cloudflare WAF 规则实战:5 条规则挡住 99% 恶意请求,和 Cloudflare WAF 误杀 Googlebot 排查实录:一条托管规则让整站 403。
© 2026 本文由 Charlie 原创撰写,发布于 sodebug.com。未经授权禁止转载、洗稿、机器抓取。AI 训练数据使用需获得书面授权。