Gatsby 5中用Helmet引入jQuery和Slick时$未定义问题求助
解决Gatsby 5中Helmet引入jQuery/slick.js刷新后报错的问题
问题根源
刷新后出现$ is not defined或jquery is not defined,本质是脚本加载顺序无法保证:未刷新时脚本有缓存,加载速度快能满足依赖关系;刷新后缓存清空,网络加载时序波动导致slick或本地脚本执行时,jQuery还未完成加载。
可行解决方案
1. 给脚本添加defer属性
defer会让脚本按书写顺序加载,且等到DOM解析完成后再执行,能严格保证jQuery → slick → 本地脚本的依赖顺序。修改你的Head组件代码:
export function Head() { return ( <> <title>Simtopia</title> <Helmet> <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous" defer ></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js" integrity="sha512-XtmMtDEcNz2j7ekrtHvOVR4iwwaD6o/FUJe6+Zq+HgcCsk3kj4uSQQR8weQ2QVj1o0Pk6PwYLohm206ZzNfubg==" crossorigin="anonymous" referrerpolicy="no-referrer" defer ></script> <script src="/js/localJS.js" defer ></script> </Helmet> </> ) }
2. 在本地脚本中确保jQuery加载完成后执行
修改localJS.js,用DOM加载事件包裹代码,同时做jQuery存在性检查,避免提前执行:
document.addEventListener('DOMContentLoaded', function() { // 轮询等待jQuery加载完成 function initWithJQuery() { if (typeof $ !== 'undefined') { // 这里写你的slick初始化或其他依赖jQuery的代码 $('.your-slider').slick({ // 自定义配置项 }); } else { setTimeout(initWithJQuery, 50); } } initWithJQuery(); });
3. 改用Gatsby官方推荐的gatsby-browser.js注入脚本
Gatsby 5更推荐通过gatsby-browser.js处理全局脚本,能通过onload事件精准控制加载顺序:
在项目根目录创建/修改gatsby-browser.js:
export function onClientEntry() { // 加载jQuery const jqueryScript = document.createElement('script'); jqueryScript.src = 'https://code.jquery.com/jquery-3.6.0.min.js'; jqueryScript.integrity = 'sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4='; jqueryScript.crossOrigin = 'anonymous'; jqueryScript.onload = () => { // jQuery加载完成后加载slick const slickScript = document.createElement('script'); slickScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js'; slickScript.integrity = 'sha512-XtmMtDEcNz2j7ekrtHvOVR4iwwaD6o/FUJe6+Zq+HgcCsk3kj4uSQQR8weQ2QVj1o0Pk6PwYLohm206ZzNfubg=='; slickScript.crossOrigin = 'anonymous'; slickScript.referrerPolicy = 'no-referrer'; slickScript.onload = () => { // 最后加载本地脚本 const localScript = document.createElement('script'); localScript.src = '/js/localJS.js'; document.body.appendChild(localScript); }; document.body.appendChild(slickScript); }; document.body.appendChild(jqueryScript); }
这种方式完全避免了加载时序冲突,是最稳定的解决方案。
内容的提问来源于stack exchange,提问作者Piotr Kondziela
相关产品推荐
相关产品推荐

