简体   繁体   English

将 Bootstrap 添加到 Gatsby 会产生“未捕获的类型错误:无法读取未定义的属性‘fn’”

[英]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 ).Helmetgatsby-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.

相关问题 未捕获的TypeError:无法读取未定义的属性&#39;fn&#39; - Uncaught TypeError: Cannot read property 'fn' of undefined 无法读取未定义/未捕获类型错误的属性“fn”:$(...).daterangepicker 不是函数 - Cannot read property 'fn' of undefined / Uncaught TypeError: $(...).daterangepicker is not a function 未捕获的TypeError:无法读取未定义的属性'fn',电子2,角6? - Uncaught TypeError: Cannot read property 'fn' of undefined, electron 2, angular 6? 未捕获的TypeError:无法使用Gatsby和graphQl读取未定义的属性“数据” - Uncaught TypeError: Cannot read property 'data' of undefined with Gatsby and graphQl 把手TypeError:无法读取未定义的属性&#39;fn&#39; - Handlebars TypeError: Cannot read property 'fn' of undefined Jest - TypeError:无法读取未定义的属性“fn” - Jest - TypeError: Cannot read property 'fn' of undefined Bootstrap Carousel:未捕获的类型错误:无法读取未定义的属性“offsetWidth” - Bootstrap Carousel: Uncaught TypeError: Cannot read property 'offsetWidth' of undefined GATSBY:类型错误:无法读取未定义的属性“包含” - GATSBY: TypeError: Cannot read property 'includes' of undefined Gatsby TypeError:无法读取未定义的属性“allWordpressAcfOptions” - Gatsby TypeError: Cannot read property 'allWordpressAcfOptions' of undefined Django Admin StackedInline未加载添加其他模型,未捕获的TypeError:无法读取未定义的属性&#39;fn&#39; - Django Admin StackedInline Not Loading Add Another model, Uncaught TypeError: Cannot read property 'fn' of undefined
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM