You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails Turbo结合content_for加载JS返回不执行如何禁用缓存

核心原因

Turbo Drive导航时不会全量替换<head>内容,只会做节点差异对比:已经存在的<script type="module">标签不会被移除重插。而ES模块本身有单次执行特性——同地址模块只要在当前页面生命周期里加载过一次,后续再插入相同的import脚本,浏览器也不会重新执行,这就是返回页面后功能失效的根因,不是Turbo主动缓存了你的content_for内容,是默认的head合并逻辑保留了旧脚本标签。

解决方案

按推荐优先级从高到低排列:

  • 给按需加载的脚本加Turbo原生重载标记
    这是侵入性最小的官方方案,直接给javascript_import_module_tag加data-turbo-track="reload"属性即可,修改目标页面的注入代码:

    <% content_for :head do %>
      <%= javascript_import_module_tag "foo", data: { turbo_track: "reload" } %>
    <% end %>
    

    Turbo在做head节点对比时,只要识别到带该属性的标签在导航后的新页面中不存在、或内容/属性有变化,会自动移除旧标签,等新页面的对应标签插入后,浏览器会重新触发模块执行,不需要修改全局布局逻辑。

  • 针对单页面关闭Turbo缓存
    如果该页面本身不需要Turbo的往返缓存加速,可以在页面head里注入Turbo缓存控制标签,让Turbo每次访问都重新渲染全页:

    <% content_for :head do %>
      <meta name="turbo-cache-control" content="no-cache">
      <%= javascript_import_module_tag "foo" %>
    <% end %>
    

    配置后Turbo不会留存该页面的DOM快照,离开后再返回会完整重新拉取渲染页面,所有head资源都会重新插入执行,缺点是该页面的往返导航速度会略低于缓存场景。

  • 把页面专属脚本移出head区域
    Turbo导航时会全量替换<body>内的节点,你可以把页面专属的模块脚本直接放到对应页面的body末尾,不要通过:head注入:

    <!-- 目标页面body内容的最末尾即可 -->
    <script type="module">import "foo"</script>
    

    每次进入页面时,这段脚本都会随body内容重新被解析执行,不需要额外调整Turbo配置。

注意

不要通过全局配置禁用整个head区域的缓存合并逻辑,会导致全站公共CSS、公共JS每次导航都重复加载,严重拖慢页面性能,只针对需要重载的单资源、单页面做上述配置即可。

内容的提问来源于stack exchange,提问作者derschiw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:27:20