Next.js vs React: The Difference Explained

A comparison explaining the differences between React and Next.js.

Next.js and React are two leading, popular frameworks for frontend development. We'll explain the difference between Next.js and React, and show how Next.js improves on top of React's already impressive accomplishments. Finally we'll discuss how to set your expectations as explore the Next.js ecosystem coming from React.


What is React?

Note: Feel free to skip this section if you're familiar with React, unless you want a trip down memory lane :)


First the basics - React is a frontend framework to build complex web applications with interactive user interfaces. React utilizes JSX, an HTML-like Javascript syntax.

React's History

First used in production on Facebook's newsfeed page in 2011 and later on Instagram's website in 2012 (shortly after their acquisition), React was released to the public as an open source framework in May 2013 at JSConf.

Here's the legendary video where Tom Occhino and Jordan Walke present React to the Javascript community. In it they explain the rationale and need for React. They also introduce JSX and explain the goal of the syntax. It's a great piece of open source history.

React's Breakthrough: Reactive Programming

React's breakthrough was the idea of updating the DOM of a web page in response to changes in Javascript state (hence the name "React" - it's meant to describe web UI updating  as a "reaction" to a change in state, or an update to its parameters). This concept, along with innovation of JSX, an HTML-like syntax of Javascript.


Before React: Imperative DOM Manipulation Hell

JSX makes it easy to describe view hierarchies with rich, complex parameters such as functions and objects. Before JSX, frontend developers found themselves interfacing with the DOM directly in order to update it.


This "imperative" approach to frontend development is best exemplified by jQuery, a UI framework from a generation before React, that required developers to retrieve and manually update DOM elements and their properties programmatically. The "logic" layer of the client / browser (Javascript) had to manage state as well as HTML and CSS, the user interface layers.


Javascript written from before the React era tended to read like an actual script - telling the DOM to setting up a stage with certain components (actors), in styles (costumes), bound with event handlers that describe instructions on how to change the scene in response to eg a button click.


This quickly turned into unmanageable spaghetti code for any sufficiently complex web app. In fact until React (especially Typescript-flavored React), managing this unwieldy complexity was considered one of the "intrinsically hard" things about frontend development. And in many ways, it was true: the complexity created such a compounding overhead tax to frontend codebases that it would hinder development productivity.

Enter React: The Functional Programming Paradigm

React brought functional programming to mainstream web development. React apps encourage developers to think in terms of inputs (state and props per the React docs) that map to outputs (UI). React components describe this input -> output process, and how to update the UI in response to updates in inputs. This is how a React project's components differ from an HTML component library - they have inner logic described by Javascript that makes it easy to understand how they will render differently with different inputs.


React makes it easy to build user interfaces from a set of reusable components. And all developers have to do to style their layouts is import css styles in-line with the associated components. Developers can create dynamic single page applications with complex state (choreographed by one of many state management libraries). Let's break down the specifics of what React offers to developers looking to build excellent web applications.


React's Features

JSX Syntax

The React community pioneered the JSX syntax as an HTML-like dialect of Javascript. JSX makes it immensely easy to describe reusable components in a way that looks like HTML. This encourages developers to think about the way their React components compose together in a view hierarchy. At the same time, because JSX is basically syntactic sugar over Javascript, it supports all of Javascript's functionality, and allows developers to pass functions in as properties (which are similar to properties in HTML) to their components.


Active Community

When developers were evaluating other frameworks like Ember, Angular, Backbone, and JQuery vs React - these breakthroughs ended up winning a lot of the frontend community over. At 192,000 Github stars, React is one of the most popular open source projects of all time. The community has driven a strong base of documentation and troubleshooting literature, from Stack Overflow (see  400k+ React questions) to threads in various Github repos.

All-time React downloads on NPM. Source: NPM Trends.


React's passionate community has produced so many libraries for to solve common problems in web development. The rich library ecosystem, from packages of well-styled reusable components, to state management patterns, to other tools that help with things like code splitting for automatic building size optimization, offline support, etc. makes for a very positive developer experience.


The React community is also present on the major social media platforms - with significant React conversations happening on Reddit, Twitter, Facebook, and more. React's strong user community is one of its great advantages. Without it, it might be just a javascript library.


React proved to be an incredibly flexible javascript library whose ideas influenced and laid the foundation for many frontend frameworks, including Next.js. In fact, React's ideas even found their way to powering mobile apps with React Native.


Smooth Development Process Thanks to Create React App

While the React framework was a massively simplified building web application frontends. But at first, React required a complicated toolchain, with bundlers like Webpack, and transpilers such as Babel.

Create React App logo. Source: Create React App.



The development environment for React has improved significantly with the advent of Create React App. Create React App is a library that greatly simplifies the setup and minutia of running a React project in development.

All-time Create React App downloads. Source: NPM Trends.


Create React App coordinates all the tools developers need to build their single page applications in development. Create React App is great for getting started quickly, but it can be difficult to customize your build. Over time, your web app may need more unique functionality that requires you to configure how it is bundled by Webpack.


Developers have to "eject" their React project from Create React App's managed toolchain in order to customize it, taking on the entire onus of toolchain maintenance themselves. This can add overhead to the development process moving forward.


In fact, getting accustomed to all the webpack configurations inside of Create React App can feel like a development project in its own right.


In recent years, the React ecosystem has exploded from a small pond into a whole ocean, with many frameworks built to extend React or apply its big ideas to new frontiers. One


What is Next.js?

All time Next.js downloads. Source: NPM Trends.


Next.js is a frontend framework that is built on React that aims to offer built-in methods to create powerful web applications. Its "killer use case" is a flexible, approachable, yet robust approach to server side rendering (SSR). But Next.js also offers built-in support for other powerful features like image optimization, code splitting, and static site generation.

Next.js's History

Next.js was first open sourced in October 2015. The project was started by Guillermo Rauch, an early adopter of React. You can see many of the principles that underpin the Next.js in Rauch's seminal blog post 7 Principles of Rich Web Applications. The post was written nearly a year before Next.js would debut to the world. Rauch also founded Vercel, formerly known as ZEIT, as the company that would build the default infrastructure for deploying Next.js applications.

Relationship Between React and Next.js

React and Next.js are different projects, but Next.js depends explicitly on React. Next.js is not attempting to "replace" React, but superpower it with performance enhancements that focus on how web applications are deployed and how pages are rendered and served.


It enables React developers to build more powerful React applications with less code, by handling the undifferentiated heavy lifting.


Before Next.js: Pain and Toil Building Performant Frontends

Ask any developer who has tried to implement server side rendering how steep the learning curve is. Many React developers need to produce pages that load quickly to improve search engine optimization, or just to boost plain old conversion.


But if you need any server side rendering, you'll find it very challenging to build and maintain. You have to figure out how to run React, a client-side library meant for use within a web browser, on the server. This often requires a headless browser.


Then there's the tricky problem of how to get client-side React to take over its control of the DOM without disrupting or overwriting the server side rendered HTML, because that would defeat the purpose of SSR in the first place.


Because server rendering react applications is expensive, you'll also need a well designed caching strategy. Without this you'll spend precious compute resources on every single client request.


You will also likely have many nitty-gritty details to consider for things like managing routing, cleanly separating code that renders server-side elements vs code that renders based on sessionful state, and more.


Next.js's Breakthrough: Incremental Static Regeneration

Next.js takes away all this complexity through a pattern called incremental static regeneration. We can break down the meaning of each word here.


Incremental

All pages Next.js applications basically act as their own static sites that can be created, updated, and regenerated individually. Moreover, the static generation of pages can happen (or continue) after build time. There are two ways for static generation to occur at runtime.


Case 1: Initial Static Generation

The first case is when the application receives a request for a page that was not statically generated at build time. In such a case, Next.js can serve a "fallback" version of the page while it executes `getStaticProps` to statically generate the page. Once the page's static generation is complete, Next.js adds it to the list of statically generated pages and will serve this static HTML for subsequent requests.


If the request is coming from a crawler such as a Google bot, Next.js will treat this as a `blocking` request - it will not return the fallback page but will serve the web crawler the statically rendered HTML page.


Next.js handles a lot of dull heavy lifting off the plates of frontend engineers, making it easy for them to consider both the performance needs of web crawlers and the more human user experience needs of their users (for more info, see Next.js's documentation on fallback).


Case 2: Regeneration

The second case is "revalidation", when a static page has grown stale. In this case, `getStaticProps` runs in the background so that the request can immediately be served with the already static HTML, which is then updated as soon as `getStaticProps` executes.

This process of static generation is tracked on a per-page basis. And static building of pages only happens as needed, hence the term incremental.


Static

As you can see, Next.js web apps are not simply static in the sense that they are only generated at the application's build time. Next.js's definition of static means being able to generate the HTML for a page upstream of client-side concerns, including session state, and being able to cache these pages to serve them on future requests.


"Static" in Next.js vs "Static" in Other Frameworks

This means Next.js has two important departures from frameworks that generate fully static websites at build time, where updating the site's content requires a rebuild. As we saw above, Next.js's incremental approach allows it to generate static HTML via pre-rendering after build time.


Backend Server Optional

It's worth noting here that the code for `getStaticData` only ever executes on the server side, and Next.js automatically removes this code from client-side bundles. This means that Next.js apps do not require backend api endpoints, strictly speaking. For teams that want to move quickly, they can even make direct calls to their database or ORM from `getStaticProps` without fear that their backend code will make leak onto the client. This can save resource-constrained teams a lot of overhead associated with building and maintaining api routes.


Next.js Dynamic Routes

Next.js gives developers the powerful ability to create pages with dynamic routes. Both React and Next.js have the concept of dynamic routes (though Next.js comes with a baked-in routing solution, while React apps usually rely on React Router, an external library). Dynamic routing in Next.js, when paired with incremental static regeneration, becomes a game-changing combination.


These two features combine to enable a Next.js page to accommodate an infinite number of variants and manage one's static generation individually as its own page. The killer use case for this is any public-facing content where there are many instances all with the same format, such as a product details page on an ecommerce website.

How Dynamic Routes Work in Next.js

Dynamic routes allow developers to define a routing scheme where they can specify that part of a route may be parameterized. When developers create dynamic routes for pages in Next.js, they can make it so that a single file in the pages folder can scale up to an infinite number of variants of that same page.


Each of these variants can then be statically generated and tracked incrementally by Next.js. Dynamic routes are specified by file naming convention in the `pages` directory.


Consider a file called `pages/product/[id].js` in `pages`. The `product` page would be a dynamic route, so `/product/chocolate-bar-10g` and `/product/gumball-3g` would be treated by Next.js as different instances of the `product` page.


These both would execute `product`'s `getStaticProps` but one would execute it with `chocolate-bar-10g` and the other with `gumball-3g` as their `id` parameters, accessible at `router.query`. Next.js would track these two as separate versions of the `product` page.


Support for Client Side Rendering

Moreover, unlike pure static web applications, Next.js also supports client side rendering. In fact, it encourages client side data fetching if there is a need for any functionality or UI that depends on session-specific data.


While Next.js's greatest superpowers lie in its server-side pre-rendering abilities, it is not dogmatic or constrictive of a React developer trying to fetch data on the client side.


Regeneration

By now, you may already have an idea for what Next.js means by "regeneration" in "incremental static regeneration". But it's important to understand how Next.js's regeneration is different from conventional server-side rendering.

ISR vs Server-Side Rendering

Server-side rendering means automatic server rendering executed for every single request. While Next.js does support server side rendering, it discourages it for content that can be derived and served statically.


This is for two reasons. First, it's a poor user experience (and can harm SEO) to block while the server renders the entirety of the contents on every single request.


Second, it scales poorly compared to a strategy that can harness caching via content delivery network (CDN). Regeneration improves on server side rendering because it only executes a server side render when it doesn't have any cached HTML for a given page request. Otherwise, it returns the page as cached in the CDN.

Other Features vs React

Comparing Next.js vs React yields some other interesting observations. First of all, Next.js has its own `Image` component, which handles a lot of heavy duty image optimization. Customization Next.js configuration  scales more nicely compared to vanilla CRA, because you can configure and customize your next.config.js setup without needing to "pop open the hood".


Next.js doesn't leave React behind, but instead enhances it. React is still a great framework for building web and mobile apps. The question is less Next.js vs React. It's more whether you think you're ready to climb the learning curve and master Next.js's many new ideas in exchange for the power that it unlocks.

Migrating from React to Next.js

Gradual migration to Next.js is a bit complex. While the documentation says you can adopt Next.js incrementally, in practice this is trickier than it looks. Before you migrate, the most important question you need to answer is: how do you fetch data from your backend for `getStaticProps` without any session token?


If you have other dependencies on session state at the top-level of your React app, you'll need to re-architect your app so that these no longer block meaningful content from rendering on your page. This should be done as prerequisite work before you adopt Next.js.


Once you've figured out how to render meaningful content on your pages without relying on session state, you can begin the process of migration.


Conclusion: Next.js, a Leap Forward for React and Frontends


Next.js vs React Daily Downloads. Source: NPM Trends

And as you can probably see, Next.js has so many different interweaving improvements that there will be a bit of a learning curve coming to it from React world. But it's becoming clear within the React community that Next.js will soon be the default (web) UI layer of the standard startup tech stack.


React and Next.js have both significantly improved the quality web apps, not to mention the developer experience of building them. Next.js has taken React and built many innovations on top of it.


A sophisticated web app that just a few years ago would have taken an entire team can now be built by a single developer (along with some help from Stack Overflow!).