简体   繁体   English

如何在 Gatsby 页面上包含本地 javascript?

[英]How to include local javascript on a Gatsby page?

I'm a total React newbie and I guess there is something fundamental I don't quite understand here.我是一个完全的 React 新手,我想这里有一些我不太了解的基本知识。 A default Gatsby page looks like this.默认的 Gatsby 页面如下所示。 Is there a way to use a local .js file somewhat like this?有没有办法像这样使用本地 .js 文件?

<script src="../script/script.js"></script>

What I would like to achieve is to have react ignore script.js but still have the client side use it.我想要实现的是让 react 忽略script.js但仍然让客户端使用它。 A default Gatsby page looks like this, is it possible to do somerthing like that there?默认的 Gatsby 页面看起来像这样,是否可以在那里做类似的事情?

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = () => (
  <Layout>
    <SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

After several hours of frustration I finally stumbled upon discussion on GitHub that solved this for me.经过几个小时的沮丧之后,我终于偶然发现了 GitHub 上的讨论,为我解决了这个问题。 In Gatsby, there is a thing called static folder , for which one use case is including a small script outside of the bundled code.在 Gatsby 中,有一个叫做static folder的东西,它的一个用例是在捆绑代码之外包含一个小脚本。

Anyone else in the same situation, try proceeding as follows:遇到相同情况的其他人,请尝试按以下步骤操作:

  1. Create a folder static to the root of your project.在项目的根目录下创建一个static文件夹。

  2. Put your script script.js in the folder static .将您的脚本script.js放在文件夹static

  3. Include the script in your react dom with react-helmet .使用 react-helmet将脚本包含在您的 react dom 中。

So in the case of the code I posted in my original question, for instance:因此,对于我在原始问题中发布的代码,例如:

import React from "react"
import Helmet from "react-helmet"
import { withPrefix, Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = () => (
  <Layout>
    <Helmet>
        <script src={withPrefix('script.js')} type="text/javascript" />
    </Helmet>
    <SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

Notice the imports注意进口

import Helmet from "react-helmet"
import { withPrefix, Link } from "gatsby"

and the script element.和脚本元素。

<Helmet>
    <script src={withPrefix('script.js')} type="text/javascript" />
</Helmet>

This would have saved hours of my time, hopefully this does it for someone else.这会节省我几个小时的时间,希望这对其他人有用。

There are many ways to add scripts in GatsbyJS...在 GatsbyJS 中添加脚本的方法有很多种...

To execute a script on a specific page在特定页面上执行脚本

  • create a stateless scriptComponent.js file and place it inside your /src folder.创建一个无状态的scriptComponent.js文件并将其放在您的/src文件夹中。

  • in your scriptComponent.js use require() to execute the script inside useEffect() like this:在您的scriptComponent.js使用require()来执行useEffect()的脚本,如下所示:

     useEffect(() => { // This runs the script const myScript = require('../script.js') }, []) return <div />
  • To run it on client-side, you could check the window object inside your script.js file:要在客户端运行它,您可以检查script.js文件中的window对象:

     if(typeof window !== 'undefined' && window.document) { // Your script here... }
  • finally, go to the page you want to execute the script in it (eg /pages/myPage.js ), and add the component <scriptComponent />最后,到要执行脚本的页面(例如/pages/myPage.js ),添加组件<scriptComponent />

If you want to execute a script globally in (every component/page) you could use the html.js file.如果您想在(每个组件/页面)中全局执行脚本您可以使用html.js文件。

  • first, you'll have to extract the file (in case you didn't) by running:首先,您必须通过运行来提取文件(以防万一):

cp .cache/default-html.js src/html.js

  • inside your html.js file:在你的html.js文件中:
 <script dangerouslySetInnerHTML= {{ __html:` // your script here... `}} />

If you'd like to use a Gatsby plugin, which to me is no different from using an external library like Helmet (plugins are npm packages after all), you could use gatsby-plugin-load-script .如果你想使用 Gatsby 插件,对我来说这与使用像 Helmet 这样的外部库没有什么不同(插件毕竟是 npm 包),你可以使用gatsby-plugin-load-script

You can provide either the url to the src attribute or a local path.您可以提供src属性的 url 或本地路径。 If you're going to store your JS in a local file such as some-minified-js.min.js - make sure to store in the static directory at the root of your project.如果您要将 JS 存储在本地文件中,例如some-minified-js.min.js - 请确保存储在项目根目录下的static目录中。

Once you do this, you can access via the global object:完成此操作后,您可以通过全局对象访问:

global.<object or func name here>

For example, I was trying to include a very small JS library via a minified file, so I stored the file in /static/my-minified-library.min.js and then:例如,我试图通过缩小文件包含一个非常小的 JS 库,所以我将该文件存储在/static/my-minified-library.min.js ,然后:

  1. Installed the plugin: npm i --save gatsby-plugin-load-script安装插件: npm i --save gatsby-plugin-load-script
  2. Added this to my gatsby-config.js将此添加到我的gatsby-config.js
plugins: [
    {
      resolve: "gatsby-plugin-load-script",
      options: {
        src: "/my-minified-library.min.js",
      },
    },
  ],
  1. Accessed in my react component like so:在我的反应组件中访问,如下所示:
useEffect(() => {
  const x = new global.MyImportedLibraryObject();
}, []}

Just create gatsby-ssr.js file on root folder只需在根文件夹上创建gatsby-ssr.js文件

and add the following pattern for your scripts folder并为您的脚本文件夹添加以下模式

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
    />
  ])
}

Then, you at the end of dom you'll see the links to scripts然后,在 dom 的末尾,您将看到脚本的链接在此处输入图片说明

Gatsby uses html.js in the src folder. Gatsby 在 src 文件夹中使用 html.js。 Not index.html like most react projects.不像大多数反应项目那样 index.html 。

Example html.js file:示例 html.js 文件:

import React from "react"
import PropTypes from "prop-types"

export default class HTML extends React.Component {
  render() {
    return (
      <html {...this.props.htmlAttributes}>
        <head>
          <meta charSet="utf-8" />
          <meta httpEquiv="x-ua-compatible" content="ie=edge" />
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
          />
          {this.props.headComponents}
        </head>
        <body {...this.props.bodyAttributes}>
          {this.props.preBodyComponents}
          <div
            key={`body`}
            id="___gatsby"
            dangerouslySetInnerHTML={{ __html: this.props.body }}
          />
          {this.props.postBodyComponents}
        </body>
      </html>
    )
  }
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

For adding custom Javascript using dangerouslySetInnerHTML inside src/html.js :要添加自定义的Javascript使用dangerouslySetInnerHTMLsrc/html.js

<script
  dangerouslySetInnerHTML={{
    __html: `
            var name = 'world';
            console.log('Hello ' + name);
        `,
  }}
/>

You can try adding your js there but, note that your js may not work as expected.您可以尝试在那里添加您的 js,但请注意,您的 js 可能无法按预期工作。 You can always look into react-helmet for more dynamic apps and adding scripts to <head> .您可以随时查看 react-helmet 以获得更多动态应用程序并将脚本添加到<head>

Gatsby Documentation: https://www.gatsbyjs.org/docs/custom-html/盖茨比文档: https : //www.gatsbyjs.org/docs/custom-html/

You can do this very easily with the Gatsby plugin "gatsby-plugin-load-script."您可以使用 Gatsby 插件“gatsby-plugin-load-script”轻松完成此操作

Simply do this:只需这样做:

  1. Create a folder named static at the root of your gatsby app在 gatsby 应用程序的根目录下创建一个名为static的文件夹
  2. Place your script in it将您的脚本放入其中
  3. Add the following configuration in gatsby-config.jsgatsby-config.js添加以下配置
    {
      resolve: 'gatsby-plugin-load-script',
      options: {
        src: '/test-script.js', // Change to the script filename
      },
    },

React works with dynamic DOM. React 使用动态 DOM。 But for rendering it by browser, your web server should send a static index page, where React will be included as another script tag.但是为了通过浏览器呈现它,您的 Web 服务器应该发送一个静态索引页面,其中 React 将作为另一个script标签包含在内。

So, take a look on your index.html page, which you can find in public folder.因此,请查看您的index.html页面,您可以在public文件夹中找到该页面。 There you could insert your script tag in the header section, for example.例如,在那里您可以在标题部分插入您的script标记。

I'm not sure if anyone still needs this answer, but here it goes:我不确定是否有人仍然需要这个答案,但它是这样的:

The answer by Elliot Marques is excellent. Elliot Marques 的回答非常好。 If you need it for a local file, upload the script to Github and use a service like JSDelivr .如果本地文件需要它,请将脚本上传到 Github 并使用JSDelivr 之类的服务。 It saves a lot of time and stress.它可以节省大量时间和压力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM