Next.js vs React: The Difference Explained
If you're looking for a product designer, you're probably wondering what questions to ask to find the best candidate. Interviewing a product designer can be tricky - after all, this is someone who will be responsible for designing and bringing your product to life. This blog post will discuss how to interview a product designer and what questions to ask them before deciding. We'll also provide tips on how to evaluate their responses. Let's get started!
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 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.
React's Breakthrough: Reactive Programming
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 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 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.
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.
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.
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.
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.
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?
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 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.
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.
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.
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
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!).