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
相关产品推荐
相关产品推荐

