Lessons Learned Building in Next.js

Part 3: Testing, Deploying, and Running

Brandon Richey
May 24, 2017 · 8 min read

Last Updated: 5/9/2017

Oh man, this crab. This crab, everyone. This crab.

Previous Post in this Series

Current Versions:

  • React: v15.4
  • next.js: v2.3

Where We Left Off

Testing with Jest/Enzyme

Directory Structure: __tests__ at root level

- (root)/
- __tests__/
- pages/
- index.test.js
- components/
- hello.test.js
- pages/
- index.js
- components/
- hello.js

If you try to place a __tests__ inside of pages/ or something similar to that structure, you might end up getting a lot of errors when you try to build your app via next build. You’ll also need to change your .babelrc file for things to work correctly:

"env": {
"development": {
"presets": ["next/babel"]
"production": {
"presets": ["next/babel"]
"test": {
"presets": ["es2015", "next/babel"]

Basically, for the test environment, we need to let babel know that it should be using the es2015 presets as well as everything next provides for the test to work (such as support for JSX). Finally, you’ll want to modify the package.json file to provide a few extra helper commands you can run from your command line in your next.js project.

package.json changes

"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"

Now you can have your test watcher waiting for any changes to files with npm run test:watch (or yarn test:watch, or run them as a one-time deal with npm test (or yarn test)!


Building on Production

From there, you’ll SSH into that box and begin the build process with npm install in the directory of your project. Assuming that all went well, you can then run npm run build or yarn build to start building the production-ized version of your site. Finally, when that’s all done, you can run npm start or yarn start to begin running your app!

Setting up environment configs with dotenv

Adding dotenv and configuring


And finally, if you haven’t already customized your webpack configuration through next.config.js, you’ll need to create that file. From there, add the following:

const webpack = require('webpack');require('dotenv').config();module.exports = {
webpack: config => {
new webpack.DefinePlugin({
'process.env.API_HOST': JSON.stringify(process.env.API_HOST),
'process.env.PORT': JSON.stringify(process.env.PORT)
return config;

What this will do is allow Webpack to detect any calls to process.env.WHATEVER (depends on what values you expose in the above config file), and replace them with the appropriate values! This will be enough to allow you to expose process.env.WHATEVER in your client files or services or what have you and make sure they’re functioning the same in dev mode, production mode, server mode, client mode, whatever!

Running the app

Configuring SSL

Configuring nginx

server {
listen 80;
listen [::]:80;
server_name mygreat.site;
return 301 https://$host$request_uri;
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/mygreat.site-0001/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mygreat.site-0001/privkey.pem;
server_name mygreat.site;location / {
proxy_pass http://localhost:1234;
client_max_body_size 5m;

Final Thoughts

What you get here, though, is a slightly more opinionated approach to things like project layout and I’ve found that it forced me into better design habits through making the alternatives just plain too hard to do or not worthwhile to pursue in the first place! I can’t just shoehorn Redux state all over the place because next.js won’t let you do that without jumping through substantial, possibly-on-fire hoops!

The server-side/client-side thing can run you into a couple of weird issues where a page works when you navigate to it, but the moment you hit refresh the page breaks (or vice-versa!), which can be very difficult to debug at times. In addition, I found the error handling and stacktraces to be more useful in general in my create-react-app project vs. my next.js project.

Next, the performance! On a fast machine with a fast network connection, I found the general impressions of speed and load times to be roughly equivalent. I also had this app powered by an Elixir/Phoenix API, which meant that the full load time for multiple items getting populated from the API was still well under 1s from start to DOMContentLoaded (generally anywhere from 500ms to 1s). That’s nothing to scoff at for a relatively small and underpowered Linode VPS!

In terms of the time frame, I went from a mostly complete create-react-app to a fully-functioning next.js app in the span of about two days, and a good chunk of that was just figuring things out (and playing Mario Kart in between). Overall, it was a fun project and I think I made the right call bringing next.js into my app. My project is smaller, better organized, and faster, and all of those are wins in my book. I wouldn’t say anything I learned was too heavily next.js-specific either, so that other fear of mine was soundly squashed by the end of the project!

Check out my new books!

This covers everything you need to know to become proficient using Create React App v2 to become a better, more productive front-end developer, and really dive deep into the details of Create React App all while building a new React project from scratch!

And, of course, my Phoenix Web Development book is also still available if you want to learn more about Elixir web development:

I’m really excited to finally be bringing this project to the world! It’s written in the same style as my other tutorials where we will be building the scaffold of a full project from start to finish, even covering some of the trickier topics like file uploads, Twitter/Google OAuth logins, and APIs!

Brandon Richey

Written by

I am a software engineer, and now, published author! Check out my new book at https://www.packtpub.com/web-development/phoenix-web-development

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade