🎉 FOSSA Acquires Dawn Labs READ MORE →
Skip to content

October 1, 2018

Migrating to Static Next.js and Now

I little over a year ago my friends and I released a little app called Carbon, and since then it has gone through a ton of development and upgrades.

Before our latest upgrade, the entire site was deployed as a Next.js monolith with Now, ZEIT’s deployment platform. Our server rendered our Next.js app, handled a number of API endpoints, and also spun up a puppeteer process for our Safari support. Really, it handled more than it should. It really never made sense to have the two coupled, but we needed to ensure a few things were possible before we could make the split.

Dynamic Routing in a Static Build

We needed to support somewhat dynamic routing, since our /** endpoint is how we load GitHub Gist’s into Carbon. This is not possible with a static export of Next.js on its own, however, ZEIT recently released static rewriting in Now.

We utilized this functionality, updating our now.json to include the necessary rewrites and set our type to static. Since ZEIT recently announced static builds with Docker, even if you are using a Dockerfile to build your app (like we are), your deployment will still be marked as a static build if you have type: 'static'.

Our `now.json`

For our case, we just needed to add RUN next export -o /public to our Dockerfile and our static build was ready to be deployed. If you are also using Next.js, follow this example to get started.

Fetching Initial Props

Once we knew all the Gist links would use our index.html, we needed to move the data fetching from getInitalProps to componentDidMount, since Next.js will call getInitialProps at export time, and no longer at runtime. This was a relatively seamless transition, since we could just wrap the component with withRouter in order to get the necessary url and query props, and we were already setting state values in componentDidMount:

Benefits of Migrating

The main reason for separating our frontend app from our backend API was to reduce the deployment headache when dealing with puppeteer issues (puppeteer is always having issues on Alpine Linux). However, we found there are tons of other reasons for deploying statically with Now:

  • Our frontend is updated a lot more often then our backend, so separating it from our backend meant we could deploy app changes without having to deal with potential issues in our backend stack getting in the way.

  • Deploying statically does not count towards your maximum number of instances running on Now. This enables awesome things like the Now + GitHub integration with very little headache. All of our PRs are now easily verified, manually by visiting the link and with our Cypress acceptance tests.

  • Finally, what I found to be most important, deploying statically let us take advantage of the Now CDN, with zero configuration, and deploy our app around the global, instantly. Check out the latency improvements too:

Our site’s latency improved from over 2 seconds to 25 milliseconds in areas like Mumbai. Considering our second largest population of users by Country is China, this means massive gains for our users.

If you are interested in seeing the exact code changes we made, you can check out the entire transformation in this pull request.

About the Author

Mike Fix is a partner at dawn, a holistic product studio dedicated to ambitious creation. Mike, and dawn, have built products in the past for companies big and small. If you or your company need help building with Next.js, Now or React, do not hesitate to reach out at [email protected].

Let’s chat 👋

If you would like to reach us, please contact Brian, Jake, orMike individually.