My Gatsby site can't be deployed to Netlify because of a WebpackError: ReferenceError: window is not defined
I've tried:
if(window !== undefined)
checks which didn't workif (typeof window !== 'undefined') {
require('scrollmagic')
require('scrollmagic-plugin-gsap')
}
which didn't workI noticed that the import statement import Scrollmagic from 'scrollmagic'
already causes the error because I once tried deploying the site without any scrollmagic code except for the import.
The scrollmagic part of my component looks like this (I deleted some irrelevant variable assignments in this example):
import React, { useRef, useEffect } from 'react'
import ScrollMagic from "scrollmagic"
import { TweenMax, TimelineMax, Power3, TweenLite, TimelineLite } from "gsap"
import { ScrollMagicPluginGsap } from "scrollmagic-plugin-gsap";
const Techstack = () => {
ScrollMagicPluginGsap(ScrollMagic, TweenMax, TimelineMax);
const techs = useRef()
const trigger = useRef()
useEffect(() => {
let controller = new ScrollMagic.Controller()
const techitems = techs.current.children
const tl = new TimelineMax
for (let i = 0; i < techitems.length; i++) {
new ScrollMagic.Scene({
triggerElement: techitems[i],
})
.setTween(TweenLite.from(techitems[i], 1, { opacity: 0, x: -300, ease: Power3.easeOut }))
.addTo(controller)
}
}, [])
return (
<TechstackContainer ref={trigger} id="trigger">
<ContentWrapper ref={techs}>
<StyledTechstackText>
Ich baue Webseiten und Apps, am liebsten mit:
</StyledTechstackText>
{stack.map(el => {
return <TechItem>{el}</TechItem>
})}
</ContentWrapper>
</TechstackContainer>
)
}
How would I go about it?
I can't see where do you call window
on your code but the way to solve this all issues is to delay the window
call after the component is rendered using a componentDidMount
(in class-based component) or useEffect
with empty deps ([]
) in stateless-based component. So, you need to do something like this:
useEffect(() => {
if(typeof window !== undefined){
let controller = new ScrollMagic.Controller()
const techitems = techs.current.children
const tl = new TimelineMax
for (let i = 0; i < techitems.length; i++) {
new ScrollMagic.Scene({
triggerElement: techitems[I],
})
.setTween(TweenLite.from(techitems[i], 1, { opacity: 0, x: -300, ease: Power3.easeOut }))
.addTo(controller)
}
}
}, [])
Note the typeof window !== undefined
condition.
However, if you are using third-party libraries that uses the window to do their stuff, you will need to put this snippet in your gatsby-node
:
exports.onCreateWebpackConfig = ({ actions, loaders, getConfig, stage }) => {
const config = getConfig();
config.module.rules = [
// Omit the default rule where test === '\.jsx?$'
...config.module.rules.filter(
rule => String(rule.test) !== String(/\.jsx?$/)
),
// Recreate it with custom exclude filter
{
...loaders.js(),
test: /\.jsx?$/,
// Exclude all node_modules from transpilation, except for 'swiper' and 'dom7'
exclude: modulePath =>
/node_modules/.test(modulePath)
},
];
if (stage.startsWith('develop') && config.resolve) {
config.resolve.alias = {
...config.resolve.alias,
'react-dom': '@hot-loader/react-dom'
}
}
};
According to Gatsby documentation:
One solution is to customize your webpack configuration to replace the offending module with a dummy module during server rendering.
Source: https://www.gatsbyjs.org/docs/debugging-html-builds/#fixing-third-party-modules