Next.js: The new way to build websites

Daniel Rotter
Agent_sh
Published in
6 min readJan 3, 2017

The first time I have heard about Next.js was the talk from Guillermo Rauch at ReactiveConf 2016 in Bratislava. I liked the idea from the very beginning of his talk. You can basically build a React app being a server rendered website with client side transitions for links. That means you get the best of client rendered single page applications and server rendered websites.

But what I like most about Next.js is how easy it is to start a website with it. I especially realized that after giving a workshop at a local user group, where also people without any former knowledge about React were able to build a simple website with this new technology. They primarily liked the fact that the transition from an usual website to a Next.js application could be made progressively, which was very useful when migrating the AgentConf website. This article will give you a very short introduction to Next.js, so that you can understand the most basic ideas.

Setup Next.js

Installing Next.js is as easy as installing any other package with Yarn (or npm).

yarn add next

Then you have to adapt the resulting package.json file with a new script, which will allow you to run a development server on http://localhost:3000.

{
"scripts": {
"dev": "next"
},
"dependencies": {
"next": "^1.2.3"
}
}

Running the following command will start the server. However, this will fail currently because we have no pages defined yet.

yarn run dev

Adding a page

Creating a new page is very simple: Just add a React component to a folder named pages. The name of the file will directly map to its URL. The file called index.js will be the home page. Using the functional components of React and the new arrow functions from ES6 a simple component can look like this:

// pages/index.js
import React from 'react';
export default () => <div>Hello World!</div>;

Congratulations! If you now start the development server again it will be working, and you already see a welcoming “Hello World!” on the index page.

Of course you can also create and use other React components to maximize code reusability. I think that’s one thing that makes this so powerful: You can implement Atomic Design without having to use something like PHP for templating anymore!

Client-side routing

Until now we only get single pages returned from the server, but we would like to only load parts of the page when clicking on links. This is possible with the Link module of Next.js.

To showcase this, we need another page we can link to first.

// pages/about.js
import React from 'react';
export default () => <div>About</div>;

This will show the text “About” on http://localhost:3000/about. This reveals another great feature: Hot code reloading is also already setup for you, so you don’t have to restart the development server in order to see the page on that URL.

If we want to link to that page from the home page we can simply use the Link module:

// pages/index.js
import React from 'react';
import Link from 'next/link';
export default () => <div>
Hello World!<br/>
Feel free to read something <Link href="/about">about us</Link>!
</div>;

Go to http://localhost:3000 and click on the link. You will realize that the URL is rewritten and the new content is shown. The route transition was also pretty fast, because only the new data that is required was loaded from the server. And if you reload the page again you’ll see that the entire page is rendered on the server.

Take some time to realize what a huge win that is! Every single page has its own route automatically and can be isomorphically rendered on the server and on the client. So we’ve got the flexibility of a single page application combined with the SEO advantages of a plain old website built with pure HTML.

Styling the website

You can do styling the old way with CSS stylesheets, put that stylesheet under the static folder, and include the stylesheet with a link as you already know it. The URL to be include can be inferred from your folder structure. The content of the static folder will simply be served at http://localhost:3000/static.

But Next.js also includes Glamor, which has a few advantages over the old approach. Probably the most important one is that it enables us to use CSS in a similar fashion as CSS modules. Just to get an idea, there is a simple style added to the index page:

import React from 'react';
import Link from 'next/link';
import css from 'next/css';
const divStyle = css({
color: 'red'
});
export default () => <div className={divStyle}>
Hello World!<br/>
Feel free to read something <Link href="/about">about us</Link>!
</div>;

This is quite interesting, especially the section where divStyle is added to the div. What glamour is doing here, is returning a randomized class name. This way you never have to worry about breaking styles at other places when changing some CSS, since it will only affect the component the CSS have been defined in. This should prevent CSS from turning into a read-only code base, in which everybody is afraid to make changes, because the change might break some other part of the page.

Fetching data from an external server

A quite common requirement is to load data from some other service and display something based on that. A possible use case is a headless CMS, in which a content manager would edit some content. The CMS then also offers something like a REST API to the content. We are going to use that to display some data.

Therefore we cannot use the arrow syntax for React component anymore, because we have to implement another method called getInitialProps. This one is defined as async, so that it can also use asynchronous requests to get the data.

// pages/data.js
import React from 'react';
import fetch from 'isomorphic-fetch';
export default class extends React.Component {
static async getInitialProps() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
return data;
}
render() {
return <div>
<h1>{this.props.title}</h1>
<p>{this.props.body}</p>
</div>;
}
}

In case you already know about the async/await functionality, there shouldn’t be too many new things here. The only other thing worth mentioning is the isomorphic-fetch package. Since fetch is already implemented in some browsers, it is very handy to use. But there is one big problem with this approach: It’s only known on the browser, but not on the server. And this is where the isomorphic-fetch jumps in.

It allows the server itself to also fetch data from another service. You can also check it out. If you access http://localhost:3000/data directly there is no additional XHR request made. But if you link the page on another page and access it via a client route transition the XHR request will be made from the browser.

Build for production

The development server is not very useful for running a website in production, because all the convenience features Next.js adds are more or less performance killers and the code is not minified. However, Next.js can build the page ahead of time and allows to serve these files.

In order for that to happen you have to add two more scripts to the package.json file:

{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "^1.2.3"
}
}

Afterwards you can us the following commands to build resp. start a server with the website:

yarn run build
yarn run start

Conclusion

I love the way simple websites are build with Next.js. Combining server-rendering with client-rendering is a huge deal. And using React as a basis enables us to build websites in a clean way. Also patterns like Atomic Design are a lot easier to implement like this.

There is a little bit more stuff to discover here, although Next.js is a quite small framework. But I wanted to keep this post as simple as possible.

If you got interested I can recommend you to checkout the repository for the workshop I’ve done, the official Next.js repository and the blogpost from the creators of Next.js, where they are explaining more about the ideals behind this project.

Trust the chef and go Next(JS)

--

--

Daniel Rotter
Agent_sh

Studied and lecturing Computer Science at FH Vorarlberg, organizes @VlbgWebDev, works at @Sulu, programming in php, symfony, javascript.