[英]Adding Bootstrap to Gatsby produces "Uncaught TypeError: Cannot read property 'fn' of undefined"
I'm using Gatsby 2.13.50 (CLI: 2.7.14).我正在使用 Gatsby 2.13.50(CLI:2.7.14)。 I'm trying to add Bootstrap 4 to my base template at /src/components/layout.js.我正在尝试将 Bootstrap 4 添加到位于 /src/components/layout.js 的基本模板中。 It's used by /src/pages/index.js.它由 /src/pages/index.js 使用。 Basically the directory structure as taught by most beginner tutorials.基本上是大多数初学者教程所教的目录结构。
I keep getting this error:我不断收到此错误:
Uncaught TypeError: Cannot read property 'fn' of undefined
at bootstrap.js:6
at bootstrap.js:6
at bootstrap.js:6
Several solutions online say that it's because bootstrap.js is loading before jquery.js and popper.js.网上的几个解决方案都说是因为bootstrap.js是在jquery.js和popper.js之前加载的。 They say placing jquery.js and popper.js first and bootstrap.js last would solve it.他们说首先放置 jquery.js 和 popper.js,最后放置 bootstrap.js 可以解决这个问题。 My results vary depending on how I bring them into the file.我的结果因我如何将它们引入文件而异。
First, the code in layout.js:首先是layout.js中的代码:
import React from "react"
import Header from '../components/header'
import '../styles/bootstrap-4.3.1-dist/css/bootstrap.css'
import { withPrefix } from "gatsby"
// If I import them like this, Gatsby cannot find the files.
// import '../styles/site_js/jquery.js'
// import '../styles/site_js/popper.js'
// import '../styles/site_js/bootstrap.js'
import { Helmet } from "react-helmet"
const Layout = (props) => {
return (
<div>
<Header />
<main role="main" className="container">
{props.children}
</main>
// If I do this, the error happens all the time.
{/* <Helmet>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</Helmet> */}
// If I do this, the error happens once every handful of times.
<Helmet>
<script src={withPrefix('site_js/jquery.js')} type="text/javascript" />
<script src={withPrefix('site_js/popper.js')} type="text/javascript" />
<script src={withPrefix('site_js/bootstrap.js')} type="text/javascript" />
</Helmet>
</div>
)
}
export default Layout
I found three ways to bring the JavaScript files into layout.js.我找到了三种将 JavaScript 文件导入 layout.js 的方法。
The first one imports the files like this:第一个导入这样的文件:
import '../styles/site_js/jquery.js'
import '../styles/site_js/popper.js'
import '../styles/site_js/bootstrap.js'
With the above, Gatsby fails to compile.有了上述内容,Gatsby 无法编译。 It gives this error for all three files:它为所有三个文件给出了这个错误:
Module not found: Error: Can't resolve 'popper.js' in '/home/testjs/hayatdemo/src/styles/site_js'
I double-checked and the files exist at that file path.我仔细检查过,文件存在于该文件路径中。 So, I don't know what's wrong.所以,我不知道出了什么问题。
The second loads the three files from external sources:第二个从外部源加载三个文件:
<Helmet>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</Helmet>
With this, Gatsby compiles, but the error appears every time I reload the page.有了这个,Gatsby 编译,但每次我重新加载页面时都会出现错误。
Finally, this solution says to add the files to /static in the root directory and call them with the help of withPrefix()
.最后,这个解决方案说将文件添加到根目录中的 /static 并在withPrefix()
的帮助下调用它们。 Like so:像这样:
<Helmet>
<script src={withPrefix('site_js/jquery.js')} type="text/javascript" />
<script src={withPrefix('site_js/popper.js')} type="text/javascript" />
<script src={withPrefix('site_js/bootstrap.js')} type="text/javascript" />
</Helmet>
This works for the most part but the error returns once every handful of reloads.这在大多数情况下有效,但每重新加载一次就会返回一次错误。
How do I solve this problem?我该如何解决这个问题?
I know JS files load in the order they are placed.我知道 JS 文件是按照它们的放置顺序加载的。 But, just to make extra sure that they really, really, really do that, I decided to override Gatsby's default-html.js so that I could add jquery.js and popper.js to the <head>
tag.但是,只是为了确保他们真的、真的、真的这样做了,我决定覆盖 Gatsby 的 default-html.js,这样我就可以将 jquery.js 和 popper.js 添加到<head>
标签中。
I don't know what default-html.js does.我不知道 default-html.js 是做什么的。 I just have a feeling it loads first and acts as some sort of basis for the whole project.我只是觉得它首先加载并充当整个项目的某种基础。
So, following Gatsby's docs on default-html.js , I first ran cp .cache/default-html.js src/html.js
.因此,按照 Gatsby 关于default-html.js的文档,我首先运行cp .cache/default-html.js src/html.js
。
Now that it's named html.js in /src, I opened it up and added the two JS files to the <head>
section:现在它在 /src 中被命名为 html.js,我打开它并将两个 JS 文件添加到<head>
部分:
import { withPrefix } from "gatsby"
<head>
...
<script async src={withPrefix('site_js/jquery.js')} type="text/javascript" />
<script async src={withPrefix('site_js/popper.js')} type="text/javascript" />
</head>
To make things load just a bit fast, I added async
to their <script>
tags following this wee article.为了让加载速度稍微快一点,我在这篇文章之后在他们的<script>
标签中添加了async
。
Now, it works perfectly.现在,它完美运行。
However, I think the trade-off is, because the JS files load first, it might affect loading time.但是,我认为权衡是,因为首先加载 JS 文件,它可能会影响加载时间。 The files are not big and it's not critical for my project so I think it's ok.文件不大,对我的项目来说并不重要,所以我认为还可以。 Maybe if loading time is more critical in future I might try npm install bootstrap
or some other solution.也许如果将来加载时间更重要,我可能会尝试npm install bootstrap
或其他一些解决方案。
Best way to add Bootstrap and related dependency with gatsby is adding them in gatsby-browser.js
like following:使用 gatsby 添加 Bootstrap 和相关依赖项的最佳方法是将它们添加到gatsby-browser.js
,如下所示:
Step 1: Run npm i bootstrap jquery popper.js
第 1 步:运行npm i bootstrap jquery popper.js
Step 2: In gatsby-browser.js
add following imports第 2 步:在gatsby-browser.js
添加以下导入
import "bootstrap/dist/css/bootstrap.min.css";
import "jquery/dist/jquery.min.js";
import "popper.js/dist/popper.min";
import "bootstrap/dist/js/bootstrap.min.js";
Note: if
gatsby-browser.js
is already present and contains ES5 code, then that needs to converted to ES6 first注意:如果gatsby-browser.js
已经存在并且包含 ES5 代码,则需要先将其转换为 ES6
Script tags should be placed at the end of page.脚本标签应该放在页面的末尾。
Whereas Helmet
and gatsby-plugin-load-script
try to append script into the head
(see link ).而Helmet
和gatsby-plugin-load-script
尝试将脚本附加到head
(见链接)。
Basically, you just need a gatsby-ssr.js
file like this, no need plugin at all.基本上,你只需要一个像这样的gatsby-ssr.js
文件,根本不需要插件。
Create gatsby-ssr.js
创建gatsby-ssr.js
import React from 'react'
export const onRenderBody = ({ setPostBodyComponents }) => {
setPostBodyComponents([
<script
key="https://code.jquery.com/jquery-3.2.1.slim.min.js"
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossOrigin="anonymous"
defer
/>,
<script
key="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossOrigin="anonymous"
defer
/>,
<script
key="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossOrigin="anonymous"
defer
/>
])
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.