Next.js中引入jQuery与Bootstrap后出现Bootstrap依赖jQuery未定义的报错求助
Next.js中Bootstrap依赖jQuery但已加载仍报错的问题
我正在使用Next.js框架,同时引入了jQuery、Bootstrap以及其他若干JavaScript库。以下是我的_app.js代码:
import React from 'react'; import { Layout } from '../components'; import { Toaster } from 'react-hot-toast'; import Script from "next/script"; function MyApp({ Component, pageProps }) { return ( <> <Script src="/js/jquery-2.1.1.min.js" type="text/javascript"></Script> <Script src="/js/bootstrap.min.js" type="text/javascript"></Script> <Script type="text/javascript" src="/js/jstree.min.js" ></Script> <Script type="text/javascript" src="/js/template.js" ></Script> <Script src="/js/common.js" type="text/javascript" ></Script> <Script src="/js/global.js" type="text/javascript" ></Script> <Script src="/js/owl.carousel.min.js" type="text/javascript" ></Script> <Layout> <Toaster /> <Component {...pageProps} /> </Layout> </> ) } export default MyApp
但我遇到了如下运行时错误:
Unhandled Runtime Error Error: Bootstrap's JavaScript requires jQuery Call Stack /js/bootstrap.min.js (6:37)
奇怪的是,在浏览器开发者工具的Elements面板中可以看到这些文件已经加载完成。请问该如何解决这个问题?
解决办法
这个问题的核心原因是Next.js的Script组件默认采用异步加载策略,就算你按顺序写了脚本标签,浏览器也可能并行加载它们,导致Bootstrap在jQuery完全加载并准备好之前就执行了。另外,Next.js的模块机制可能没有把jQuery自动暴露到全局window对象上,Bootstrap的JS代码找不到window.jQuery就会报错。
下面是两种靠谱的解决方式:
方式一:用Next.js Script组件控制加载顺序与全局挂载
修改你的_app.js,给脚本配置合适的加载策略,并手动把jQuery挂载到全局:
import React from 'react'; import { Layout } from '../components'; import { Toaster } from 'react-hot-toast'; import Script from "next/script"; function MyApp({ Component, pageProps }) { return ( <> {/* 优先加载jQuery,用beforeInteractive确保它在其他脚本前就绪 */} <Script src="/js/jquery-2.1.1.min.js" type="text/javascript" strategy="beforeInteractive" onLoad={() => { // 手动把jQuery挂载到window,让Bootstrap能找到它 window.jQuery = window.$ = require('/js/jquery-2.1.1.min.js'); }} /> {/* 所有依赖jQuery的脚本都用afterInteractive,确保在jQuery加载后执行 */} <Script src="/js/bootstrap.min.js" type="text/javascript" strategy="afterInteractive" /> <Script type="text/javascript" src="/js/jstree.min.js" strategy="afterInteractive" /> <Script type="text/javascript" src="/js/template.js" strategy="afterInteractive" /> <Script src="/js/common.js" type="text/javascript" strategy="afterInteractive" /> <Script src="/js/global.js" type="text/javascript" strategy="afterInteractive" /> <Script src="/js/owl.carousel.min.js" type="text/javascript" strategy="afterInteractive" /> <Layout> <Toaster /> <Component {...pageProps} /> </Layout> </> ) } export default MyApp
关键配置说明:
strategy="beforeInteractive":这个策略会在React开始渲染前同步加载脚本,适合jQuery这种基础依赖,保证它在所有后续脚本执行前就已经加载完成并挂载到全局。onLoad回调:Next.js的模块系统默认不会把第三方库暴露到全局,所以我们手动把jQuery赋值给window.jQuery和window.$,这样Bootstrap的JS就能找到它了。strategy="afterInteractive":依赖jQuery的脚本用这个策略,它们会在页面交互可用后加载,但会等待beforeInteractive的脚本执行完成,完美适配依赖顺序。
方式二:用传统同步脚本标签(应急用,不推荐长期使用)
如果想快速验证问题,你可以在_document.js里添加传统的同步script标签,浏览器会严格按顺序加载执行:
// pages/_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; class MyDocument extends Document { render() { return ( <Html> <Head> {/* 这里放你的meta标签、样式表等 */} </Head> <body> <Main /> <NextScript /> {/* 按顺序添加同步脚本,浏览器会从上到下依次加载执行 */} <script src="/js/jquery-2.1.1.min.js" type="text/javascript"></script> <script src="/js/bootstrap.min.js" type="text/javascript"></script> <script type="text/javascript" src="/js/jstree.min.js"></script> <script type="text/javascript" src="/js/template.js"></script> <script src="/js/common.js" type="text/javascript"></script> <script src="/js/global.js" type="text/javascript"></script> <script src="/js/owl.carousel.min.js" type="text/javascript"></script> </body> </Html> ); } } export default MyDocument;
不过这种方式会阻塞页面渲染,影响首屏加载性能,所以更推荐第一种方式。
内容的提问来源于stack exchange,提问作者vimuth
相关产品推荐
相关产品推荐

