
ReferenceError: Window is Not Defined in Gatsby
In my current project, I oversee three associate developers; these are hyper‑intelligent junior developers, fresh out of code camp. I've always enjoyed working in a mentoring‑type role, especially when their questions can leave you unsure of the 'why' behind some of the things we do every day in web development.
Today though, I was approached about an incredibly common early‑steps issue when attempting to build a Gatsby site:
WebpackError: ReferenceError: window is not definedThis can be particularly vexing when you've inevitably been developing and running the site locally via gatsby develop with no hint of an issue. Fortunately, the answer is very, very simple.
The Cause
It may be very obvious what the issue is, but just in case: when running a build within the Node.js environment, browser Global Variables such as window or document do not exist, so any code that references them will fail unless suitably safeguarded. There are two very straightforward ways around this:
Ensure that window and/or document is defined before calling
Adding a little safeguarding to your code will ensure that we don't end up in a situation where you're attempting to call browser variables that don't exist. This isn't going to be as simple as just testing !window, but it's also not much more complicated:
// if true, then we are rendering in-browsertypeof window !== 'undefined'You can also take this one step further and check for the existence of document too if ‑ for example ‑ you need to access documentElement to toggle a classname, although in most cases this wouldn't be necessary:
typeof window !== 'undefined' && documentMove the code into the componentDidMount lifecycle
If your code sits within one of your React.js components, then you can simply move it within the component's lifecycle using componentDidMount or a useEffect hook. These only run when the component is mounted in a browser, so you can be safe in the knowledge that window does indeed exist at that point.
useEffect(() => { // global browser variables will always exist here}, []);Issues with Third‑Party Modules
It's all very well and good knowing how to resolve these types of build errors within your own code, but what about when the issue lies within a third‑party module which simply assumes that window always exists? Aside from opening a ticket and hoping that the developer sees the error in their ways, there are a couple of options available.
Conditionally Require a Module
Expanding on the safeguarding we discussed above, it is possible to conditionally require a module within your code:
if (typeof window !== 'undefined') { const module = require('module');}Or inline using a simple ternary:
const module = typeof window !== 'undefined' ? require('module') : null;If you go down this route, you will then ‑ of course ‑ need to ensure that each use of the module within your component is wrapped in a conditional too.
Use a dummy placeholder during build
In Gatsby, you can also tie into the Gatsby Node API and simply swap the offending module out during the SSR build process.
Direct from the Gatsby docs on the subject, simply add the following code to your gatsby‑node.js file. If your project doesn't have a gatsby‑node.js file yet, you can simply create one in the root of your project and it will be picked up next time you run Gatsby.
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => { if (stage === 'build-html' || stage === 'develop-html') { actions.setWebpackConfig({ module: { rules: [ { test: /naughty-module/, use: loaders.null(), }, ], }, }); }};I explicitly mention Gatsby in the title and throughout this article, but it's worth mentioning that the exact same is true if you come across this error on build‑time in any server‑side rendered framework, like Next.js.
Related Articles

Life as a Freelance Developer in Brighton. 
Rendering Contentful Rich Code Snippets in Gatsby. Rendering Contentful Rich Code Snippets in Gatsby

JavaScript Essentials for Freelance Web Developers. JavaScript Essentials for Freelance Web Developers

Lazy Loading in Angular: Optimising Performance. Lazy Loading in Angular: Optimising Performance

Array.includes() vs. indexOf() in JavaScript. Array.includes()vs.indexOf()in JavaScript
Leveraging JavaScript Frameworks for Efficient Development. Leveraging JavaScript Frameworks for Efficient Development

Using CommonJS to Implement Modules in JavaScript. Using CommonJS to Implement Modules in JavaScript

Controlled vs. Uncontrolled Components in React. Controlled vs. Uncontrolled Components in React

ParseInt in JavaScript: The Significance of Radix. parseIntin JavaScript: The Significance of Radix
Understanding Arrow Functions in JavaScript. Understanding Arrow Functions in JavaScript

String to Integer (atoi): Decoding Strings in JavaScript. String to Integer (atoi): Decoding Strings in JavaScript

Understanding Element Dimensions in JavaScript: Width and Height. Understanding Element Dimensions in JavaScript: Width and Height