Making Next.js and Mapbox GL JS get along
TL;DR: Mapbox GL JS does give errors when trying to render server-side. Using next’s dynamic imports and setting the optionssr: false
forces client-side rendering, making this work.
Mapbox and the window object
This is going to be a very short post, but that does not make it unimportant — I just wanted to share a solution to a problem I encountered while using next.js and Mapbox.
Without diving into great detail, Mapbox GL JS uses the global window object under the hood. When rendering components server-side as we want to do using next.js, this object does not exist.
Using dynamic imports
For this, the next
package comes with a method that allows us to dynamically import components that need client-side rendering.
So instead of importing and rendering your Mapbox component via:
// This is going to rekt your appimport Map from './client';export default () => (
<div>
<Map />
</div>
);
We’d rather import the method dynamic
, which is a default export, from thenext/dynamic
package via import dynamic from 'next/dynamic'
After this, you can dynamically import the component via:
const DynamicMap = dynamic(() => import('./client'), {
loading: () => <p>Loading...</p>
});
The dynamically loaded component is now stored in the DynamicMap
variable. Note that the dynamic()
method call takes a second argument with an optional options
object, where we can specify a React component that’s supposed to show up before the component is rendered on the client via the loading
property.
I somehow still received some errors which I resolved by also adding a ssr: false
property to the options
object, so my final code looked like this:
const DynamicMap = dynamic(() => import('./client'), {
loading: () => <p>Loading...</p>,
ssr: false
});
If you ran into the same trouble as I did, I hope this short post was useful for you. See you next time!