Gatsby项目嵌入的script仅刷新生效、页面跳转时不执行如何解决
问题原因
Gatsby 是基于 React 构建的单页应用,页面间跳转走的是客户端路由逻辑,不会触发完整的页面重载。你硬编码在 html.js 头部的脚本仅会在首次整页加载(即手动刷新场景)时加载执行一次,路由切换时不会重新加载;同时window.onload事件仅在整页资源全部加载完成时触发一次,客户端导航场景不会触发该事件。
解决方案
方案1:通过 gatsby-browser.js 监听生命周期事件(最推荐)
直接将脚本逻辑迁移到 Gatsby 官方提供的客户端生命周期文件中,可精准匹配首次加载、路由更新等多个场景:
// gatsby-browser.js 项目根目录新增/编辑该文件 const sendDataLogic = () => { console.log('worked') // 此处写入原sendData脚本的所有业务逻辑 } // 首次页面渲染完成后执行 exports.onInitialClientRender = () => { sendDataLogic() } // 每次客户端路由跳转完成后执行 exports.onRouteUpdate = () => { sendDataLogic() }
方案2:使用 Gatsby 内置 <Script> 组件引入脚本
如果需要保留独立脚本文件,可将脚本放到项目根目录的static/general/路径下,再在全局布局组件中引入官方Script组件,设置路由更新时自动执行:
// src/components/layout.js 全局布局组件 import { Script } from "gatsby" const Layout = ({ children }) => { return ( <> {/* 原有布局代码 */} <Script src="/general/sendData.js" strategy="routeUpdate" /> {children} </> ) } export default Layout
同步修改脚本内容,移除window.onload绑定,直接暴露执行逻辑即可:
// static/general/sendData.js console.log('worked') // 其他业务逻辑直接写在顶层即可
方案3:修改原生脚本适配Gatsby路由事件
如果必须保留html.js引入脚本的写法,可修改脚本内容,主动监听Gatsby的路由切换自定义事件:
// sendData.js const runLogic = () => { console.log('worked') // 原有业务逻辑 } // 兼容首次加载场景 if (document.readyState === 'complete') { runLogic() } else { window.addEventListener('load', runLogic) } // 兼容客户端路由跳转场景 window.addEventListener('gatsby-route-change', runLogic)
注意事项
- 不要直接在
html.js中用相对路径引入src目录下的脚本,打包后资源路径会发生变化,独立脚本建议放到static目录下用绝对路径引用 - 避免直接给
window.onload赋值,多次赋值会覆盖之前的绑定逻辑,用addEventListener绑定事件更安全
内容的提问来源于stack exchange,提问作者Alban denica
相关产品推荐
相关产品推荐

