Joakim Lustig's blog

Migrating from create-react-app to gatsby

January 24, 2018


I love using react for my web projects. The ease with which I can modularize pages and add advanced functionality to the projects is great.

However, one huge pain point is setting up a new projects, configuring webpack, routing etc. That's why I often use a starter kit, so I can focus on the specific project features instead of writing lots of boiler plate code.

For that purpose I have used create-react-app for a long time. Although I have always been annoyed that the projects I create require javascript to be enabled. For a while I was also a bit worried that it would hurt SEO, but after digging a bit it seems like this is not actually an issue nowadays (at least not for google, might still be a problem for other search engines), as described here for example. Even though this might not be a problem, I still don't like to require users to have javascript enabled to access even the most basic functionality.

To avoid this in the past I have sometimes used server side rendering, but the deploy, scale and cost issues that comes with the need to have a webserver to serve content compared to hosting static files is simply too much of a hassle to make it worth it.

I recently took the time to try out Gatsby, which is a static site generator for react. It's super easy to get started if you want to try it out. There are also a number of more specific starter kits available, for example a blog starter.

After trying it out for a bit I started for real with migrating a small create-react-app I had, which contains a landing page, blog and a simple web app that lets users create name badges for their events.

The process was easy enough. I started with moving my react component folders to the new project and added my node packages from the create-react-app project to my new gatsby project.

Routing

I setup routing by calling each page component from a separate file in the pages folder of the Gatsby project. Like this:

// about.js
import React from 'react';
import About from '../Containers/About/About.js';

const AboutPage = () => (
  <About />;
);

export default AboutPage;

Then I removed all references to react-router and changed the links to Link components from the gatsby-link package.

That took care of the routing and now all the basic site functionality actually worked.

One small problem

Next step was to build the project and check that the production bundle was good to go.

error Building static HTML for pages failed

See our docs page on debugging HTML builds for help https://goo.gl/yL9lND

  76 |     let width;
  77 |     let height;
  78 |     const clientWidth = window.innerWidth
  79 |       || document.documentElement.clientWidth
  80 |       || document.body.clientWidth;
  81 |     const clientHeight = window.innerHeight


  WebpackError: window is not defined

Wait... What's this about?

Apparently you can't have references to the window object at build time. Which makes sense, since there is no browser present at that time. In this case I was even adapting the size of a DOM-element to the size of the browser window, which makes no sense if there is no client browser.

So I put some default values in case window is not defined:

const clientWidth = (typeof window !== `undefined`) ? window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth : 400;

And tried to build again.

success Building CSS — 9.176 s
success Building production JavaScript bundles — 42.182 s
success Building static HTML for pages — 5.107 s
info Done building in 58.435 sec

There we go, that was actually everything I needed to do to migrate my app to gatsby. Now my page is pre-rendered before it's sent to the client, creating a better experience for users.

Oh did I mention it's fast! I managed to lower my page load time and increase my google speed score by a lot just by migrating.

I also decided to migrate my personal website to Gatsby.


Joakim Lustig's face

Joakim Lustig

Software Developer & Data Scientist