Ran into a situation a little while ago where I needed a calendar page for something I was working on, eventually settled on FullCalendar with its React docs.
I wrote up my page and got it working with the development server, only to have the following issue when I went to build my production bundle
"window" is not available during server side rendering.
See our docs page for more info on this error: https://gatsby.dev/debug-html
1 | import * as react from 'react';
2 | import * as reactDom from 'react-dom';
> 3 | (typeof globalThis !== 'undefined' ? globalThis : window).FullCalendarVDom = {
| ^
4 | Component: react.Component,
5 | createElement: react.createElement,
6 | render: reactDom.render,
WebpackError: ReferenceError: window is not defined
Not being a JS developer normally, this led me down a bit of a rabbit hole and it took me a couple of hours to find a solution, which is
- Make sure Gatsby doesn’t try to compile the FullCalendar library in a static fashion
- Make the calendar object loadable at run time
To do this, I opened up gatsby-node.js
and added this to the bottom of the file
exports.onCreateWebpackConfig = ({stage, loaders, actions}) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /@fullcalendar\/react/,
use: loaders.null(),
},
{
test: /@fullcalendar\/daygrid/,
use: loaders.null(),
},
],
},
})
}
}
Next, I installed the react-loadable
library and wrapped the calendar on the page
$ npm install --save react-loadable
const LoadableCalendar = Loadable({
loader: () => import('@fullcalendar/react'),
loading: () => <div>Loading...</div>,
render(loaded, props) {
let Cal = loaded.default;
return <Cal {...props} />
}
})
This let me keep the same properties as the FullCalendar component normally exposes
<LoadableCalendar
plugins={[ dayGridPlugin ]}
initialView="dayGridMonth"
events={fullCalendarEvents}
/>
Build seems happy now. Hopefully this helps someone in less time than it took me.