I\'m a total React newbie and I guess there is something fundamental I don\'t quite understand here. A default Gatsby page looks like this. Is there a way to use a local .js
There are many ways to add scripts in GatsbyJS...
To execute a script on a specific page
create your script.js
file and place it anywhere inside your /src
folder.
go to the page you want to excute the script in (e.g. /pages/myPage.js
), and use require()
to execute it inside useEffect()
like this:
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:
if(typeof window !== 'undefined' && window.document) {
// Your script here...
}
If you want to execute a script globally in (every component/page) you could use html.js
file.
cp .cache/default-html.js src/html.js
html.js
file:<script dangerouslySetInnerHTML= {{ __html:` // your script here... `}} />
After several hours of frustration I finally stumbled upon discussion on GitHub that solved this for me. In Gatsby, there is a thing called static folder, for which one use case is including a small script outside of the bundled code.
Anyone else in the same situation, try proceeding as follows:
Create a folder static
to the root of your project.
Put your script script.js
in the folder static
.
Include the script in your react dom with react-helmet.
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.
React works with dynamic 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.
So, take a look on your index.html
page, which you can find in public
folder. There you could insert your script
tag in the header section, for example.
You can do this very easily with the Gatsby plugin "gatsby-plugin-load-script."
Simply do this:
static
at the root of your gatsby appgatsby-config.js
{
resolve: 'gatsby-plugin-load-script',
options: {
src: '/test-script.js', // Change to the script filename
},
},
Just create gatsby-ssr.js
file on root folder
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
Gatsby uses html.js in the src folder. Not index.html like most react projects.
Example html.js file:
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
:
<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. You can always look into react-helmet for more dynamic apps and adding scripts to <head>
.
Gatsby Documentation: https://www.gatsbyjs.org/docs/custom-html/