Using Mapbox with Next.js (Instead of Google Maps)

JW

Jonathan Wong / January 13, 2019

3 min read––– views

In the process of selecting a mapping library for dsmtech.io, I ran into a number of roadblocks. First and foremost, Google Maps has drastically changed their pricing structure.

"On June 11, 2018, we launched new Maps, Routes and Places functionality, which changes the way certain APIs and features are billed. Then on July 16, 2018, all API and feature prices changed to align with our pricing table."

As you can imagine, a lot of people are upset. In the past 6 months, I've stumbled onto a lot of projects that were using Google Maps that no longer work. This really puts a hindrance on side projects. Thus, I needed a different solution for my mapping library.

Mapbox#

Ultimately, I decided to use Mapbox.

  • It uses OpenStreetMap under the hood, which is open-source.
  • It has simple pay-as-you-go pricing.
  • It's free up to 50,000 map views per month.

Mapbox Pricing

Next.JS#

I love Next.js. This blog is actually written with it. If you've never heard of Next, here are some of the big wins for me.

  • Automatic transpilation and bundling (with Webpack and Babel).
  • Automatic code splitting.
  • Hot code reloading.
  • Server-side rendering (SSR) out of the box.
  • Static file serving.

If that sounds awesome, follow their quick-start guide to get an application up and running. For now, let's assume you already have your Next application working.

Just want the code? You can view a working example here and the code here.

Mapbox + Next.JS#

We'll take advantage of the wonderful react-map-gl library created by Uber.

yarn add react-map-gl

Now, let's create a simple Map component at components/Map.js.

import { Component } from 'react';
import ReactMapGL from 'react-map-gl';

class Map extends Component {
  state = {
    viewport: {
      width: '100vw',
      height: '100vh',
      latitude: 41.5868,
      longitude: -93.625,
      zoom: 13
    }
  };

  render() {
    return (
      <ReactMapGL
        mapStyle="mapbox://styles/mapbox/streets-v9"
        mapboxApiAccessToken="YOUR_MAPBOX_TOKEN_HERE"
        onViewportChange={(viewport) => this.setState({ viewport })}
        {...this.state.viewport}
      />
    );
  }
}

export default Map;

Note: You will need to create a Mapbox account and generate a token.

Mapbox uses the global window object under the hood, which means it can't be server-side rendered. Thus, we need to make some modifications to get things working.

Next now supports dynamic imports, which make it easy to selectively render components on the client-side. Let's modify our pages/index.js file, or whichever route you want to render the Map component.

import dynamic from 'next/dynamic';

const DynamicComponentWithNoSSR = dynamic(() => import('../components/Map'), {
  ssr: false
});

export default () => <DynamicComponentWithNoSSR />;

Finally, you'll need to include the Mapbox CSS file in your application. You can do this in a variety of ways. I chose to override _app.js and include it in the <head> like so.

<link
  href="https://api.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css"
  rel="stylesheet"
/>

At this point, you should be able to run yarn dev (which runs next) to see the map working.

Mapbox Demo with Next.js

Going Further#

Okay, we've got a map. Now what? Here are some other ideas for going further.

Discuss on TwitterEdit on GitHub
Spotify album cover

/tools/photos