You should use Next.js as your default framework for your next React application
Discover what Next.js can bring you in the development of your React applications.
Introduction
React is a great Javascript library. It has a great component system, and it offers you a way to create Single Page Applications easily.
As the React developers mention on their official website, React is a library. That means it will offer you part of the features you need to create a web application, but you’ll probably need more tools on top of it. For instance, if you create an application that requires routing, you’ll have to install react-router (or a similar library) and configure it.
If you’re not using a starting template such as create-react-app, for example, you’ll also have to do some heavy configuration using webpack and babel. You’ll then have to set up a development configuration, and a production one. This takes time and effort. It’s no fun if you have to do it every single time you start a project!
Next.js solves most of those issues. It is a framework built on top of React. It provides out of the box the features you’ll need in a Web Application.
We’ll go through it in a moment, but in summary, Next.js includes routing, optimizations for production, server-side rendering, static site generation, and more! Let’s discover those features!
What are the key features of Next.js?
Routing
Next.js offers you a routing system out of the box. That means you won’t have to deal with extra libraries to handle this topic.
Next.js offers a smart way to define your routing system. You won’t have to declare your routes in a Javascript file as you’d do with react-router, for example. You’ll describe your routes using the file system.
You’ll also have access from the beginning to a client-side routing. Instead of using standard <a>
HTML tag to navigate within your application, Next.js provides a component called <Link/>
. Not only does it enable client-side navigation, but it also allows the browser to pre-fetch the data needed on the pages the user might navigate to!
Pre-fetching
The framework will download all the resources necessary for each link that is within the user’s viewport. For instance, if you open a page containing a navigation menu that includes a route to a `/about` page. The user’s browser will download the resources needed by that page even before he clicks on it. The navigation gives the impression to be much faster from the user’s perspective.
Server-side rendering (SSR)
One of the Next.js highlight is that it gives you a simple solution to apply server-side rendering (or SSR) to your application.
When you create a new application with the create-react-app command line, your application will be, by default, a Single Page Application (SPA). When the users visit your application, the client builds the whole app: the browser downloads an HTML file whose body contains a simple div
. The browser fetches then the required Javascript files, executes them, and builds your application pages.
This process is called client-side rendering (or CSR). While this is a great way to create React applications, its major drawback is that it doesn’t perform well SEO wise. The bots used by the search engines to index the web are not executing Javascript. In the CSR scenario, the bots download the empty HTML file and then read the page. Since the Javascript isn’t running to build the page, the document will appear blank for the bot.
That’s where SSR comes into the picture. As its name shows, the SSR process will build the pages on the server first and then send it to the browser. When the client receives the page, it doesn’t need to build it. It goes the same for the search engines crawler: instead of seeing an empty page, they’ll get a full document.
While this method is excellent from an SEO perspective, it also has some disadvantages:
- You will need a server to generate the page’s structure when a user requests it. In Next.js’s case, a Node.js server handles this.
- The server builds the pages for each request: a thousand users requesting the same page will trigger a thousand generations from the server.
- Increased time to first byte (TTFB): since the server builds the page first, your browser will have to wait a bit more time to receive the response to its request.
Static Site Generation (SSG)
Static Site Generation (or SSG) is an excellent alternative to server-side rendering: while SSR builds pages at every request (at runtime), SSG builds your application pages at build time.
That means that you need to specify to Next.js how the routing of the statically generated pages looks like, fetch the required data, and run the build command. The framework will then build static HTML pages out of your source code.
Using SSG instead of SSR, you’ll keep the advantages of having excellent SEO performances while not needing a server to build your application pages. It will also benefit your users since the application’s performance will be enhanced: since you don’t have a server building the pages at runtime, the users download an HTML file (from a CDN, for instance).
One downside of SSG is the time needed to build your application: if you need an enormous amount of pages for your application, the build time can be quite long. In that scenario, you’ll also need more storage space to hold your entire application.
Let’s say that you have an extensive amount of pages changing frequently; you’d think that SSG wouldn’t be the right approach for you since you’d have to build your application every time some of the content is changing. And you’d be right!
But since its version 9.4, Next introduced Incremental Static Regeneration. This feature allows two things:
- You can generate new static pages while your application is running: let’s say that you have an e-commerce website containing thousands of products. If you generate all the pages at the build stage, it would require some time before your application is ready to be deployed. If you use Incremental Static Regeneration, you can specify to Next.js that even though some pages should be static, they shouldn’t be created during the build stage. Instead, the framework should generate them during runtime: the user requests the page, Next.js notices it doesn’t exist, it builds it on the fly, serves it to the user, and keeps it in storage with the other statically generated pages in case a user requests the same page. This solution is brilliant if you have a vast amount of pages in your application. The downside is that the first user reaching the page would have to "wait" before receiving the response, since the page needs to be built.
- It can regenerate static pages at runtime. You can ask Next.js to update a static page when a request comes in and at most once every “X” second. This feature can be handy if your pages’ content changes a lot, but you’d still want to benefit from the SSG.
Code Splitting
Next.js configures code splitting for you on the pages level. What does that mean exactly? Let’s imagine that your application is using a lot of different components and libraries. If you don’t have a code splitting configuration in place, one Javascript bundle contains your whole app. When a user visits your website, he will have to download the entire bundle, even if he sees only one page.
Code splitting solves this issue by “cutting” your application in different chunks. As said previously, Next.js is doing it on the page level: it analyzes which component or libraries the page needs, and it includes them in a specific chunk file. That way, the users download what’s needed and nothing more. This optimization can have a significant impact on your app performance.
Dynamic Imports
Dynamic imports allow you to optimize even more your bundle's size. Let’s say your application contains a calendar that appears when the user clicks on a button.
In that situation, code splitting on the pages level wouldn’t help you: Next.js would include the calendar component within the page bundle since it assumes that it is needed. That means the users will have to download the calendar component even if they don’t open it.
Dynamic imports give you the possibility to specify to Next.js how to cut your application bundle in multiple chucks. In the “calendar example”, we could determine that the application must import the calendar component only when the user clicks on a specific button. That way, Next.js places the calendar in a separate chunk downloaded on demand.
create-next-app
Create-next-app is a command similar to create-react-app. It is not really a part of Next.js. It’s a tool that helps you to get started easily with a new Next.js app. You can either use the CLI with no option, and it will generate the bare minimum application for you. Or you can pass it an --example
option, so it will base your project on one of the many Next.js examples.
Conclusion
In conclusion, with Next.js, you can benefit from outstanding features out of the box with zero configuration. It will help you increase your pages performances and your SEO visibility.
The client-side routing is great to improve the experience of your users in your application. The transition between pages appears smoother when the users navigate on the site.
If you don’t need SSR or SSG, this framework can still be useful. Code splitting and dynamic import will increase the speed the users download your application. It will be especially noticeable on mobile devices.
You’ll just have to figure out what type of rendering your website needs. Note that you can individually decide which page is using SSR or SSG!
Next also offers many other useful features that I didn’t describe in depth in this article, such as Image Optimization, Internationalization, Fast refresh, linting, easy TypeScript configuration, and more.
Thank you for reading my article. I hope you’ll give Next.js a try if you haven’t done it yet!