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

Gatsby中html.js引入的custom.js仅首次加载 跳转页面不生效如何解决

问题原因

Gatsby 是基于 React 的单页应用(SPA),站内页面导航走的是客户端路由,不会触发整页 HTML 重载,因此你写在 html.js 里的静态脚本只会在站点首次加载时执行一次。另外你代码里的 $(document).ready 事件仅在全局 DOM 首次加载完成时触发,后续路由切换是局部更新 DOM,不会再次触发该事件。
你将脚本放在 Helmet 中也无效的原因是:Helmet 会自动对比前后渲染的头部资源,相同 src 的脚本默认不会重复插入执行,因此也只会运行一次。

解决方案

下面提供三种常用实现方案,可按需选择:

方案1:路由变化时主动调用逻辑(推荐,性能最优)

先改造你的 custom.js,把需要执行的逻辑封装为全局可调用的函数,不要直接包裹在 $(document).ready 里:

// static/js/custom.js
window.runCustomLogic = function () {
  // 把你原来的所有逻辑放在这里
  console.log("in ready");
}

在项目根目录的 gatsby-browser.js(没有就新建)中使用 Gatsby 官方提供的 onRouteUpdate API,该 API 会在每次路由导航完成后触发:

// gatsby-browser.js
export const onRouteUpdate = () => {
  // 确保自定义函数已加载再调用
  if (typeof window.runCustomLogic === 'function') {
    window.runCustomLogic();
  }
}

原来 html.js 里的 custom.js 引用可以保留,负责首次加载时注册全局函数即可。

方案2:动态重复插入脚本(无需修改原custom.js)

如果不想改动现有 custom.js 的代码,可以在每次路由变化时手动移除旧脚本、插入新脚本触发执行:

// gatsby-browser.js
import { withPrefix } from "gatsby";

export const onRouteUpdate = () => {
  // 移除已存在的custom.js脚本
  const oldScript = document.querySelector('script[src$="custom.js"]');
  if (oldScript) {
    oldScript.remove();
  }
  // 插入新的脚本标签
  const newScript = document.createElement('script');
  newScript.src = withPrefix('/js/custom.js');
  newScript.type = 'text/javascript';
  document.body.appendChild(newScript);
}

注意该方案每次路由都会重新请求脚本,适合脚本逻辑比较简单的场景。

方案3:页面级绑定逻辑

如果你的自定义脚本逻辑仅需要在特定页面运行,直接在对应页面组件的 useEffect 钩子中执行即可:

import { useEffect } from "react";

const YourPage = () => {
  useEffect(() => {
    // 执行自定义逻辑
    console.log("当前页面加载时执行");
    return () => {
      // 页面卸载时的清理逻辑(比如解绑事件监听)可写在这里
    }
  }, []);

  return <div>页面内容</div>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 02:54:04