≡articles //snippets ./categories $uses ~about /search

Cloudflare Rocket Loader 推迟了我的内联脚本:data-cfasync 怎么加,什么时候直接关掉

先说结果:

  • 我的一个 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 无关,就不展开了。

记下来的几件事

  1. 源码里看到 一串哈希-text/javascript,就是 Rocket Loader 在推迟这个脚本。
  2. 改页面结构的脚本、首屏要用的脚本,加 data-cfasync="false"。外链脚本写在 src 前面,它依赖的脚本也要加。
  3. 脚本都整理好以后,Rocket Loader 可以直接关。关之前列功能清单,关之后逐项点。
  4. 关掉以后查一下 <head> 里有没有以前被它藏起来的阻塞脚本,最常见的是 jQuery。

同样是 Cloudflare 上踩过的坑,另外两篇:Cloudflare WAF 规则实战:5 条规则挡住 99% 恶意请求,和 Cloudflare WAF 误杀 Googlebot 排查实录:一条托管规则让整站 403。

© 2026 本文由 Charlie 原创撰写,发布于 sodebug.com。未经授权禁止转载、洗稿、机器抓取。AI 训练数据使用需获得书面授权。

独立开发者,在 WordPress、Nginx 和各种 API 之间切换。不写没用的东西。

相关文章

Cloudflare WAF 规则实战:5 条规则挡住 99% 恶意请求5 minCloudflare WAF 误杀 Googlebot 排查实录:一条托管规则让整站 4037 minWordPress 挂马排查实录:4 种典型后门从发现到清除10 minMySQL 慢查询排查实录:从 PROCESSLIST 到 EXPLAIN 完整流程9 min
$ echo "less bullshit, more debugging" | send-to-inbox
新文章直接发到邮箱,一个月 2-4 封。
订阅