Summary

This ebook provides a comprehensive guide to Next.js, a React framework. It explores the advantages of Next.js over React.js, including simplified frontend development, reduced tooling time, and an easy learning curve. The author highlights improvements in performance, SEO, and the continuous advancement with new features.

Full Transcript

The Ultimate Next.js Ebook Index 00 Table Of Contents Chapter 1 Birth 01 Chapter 2 Introduction 07 Chapter 3 Roadmap 15 Chapter 4 How it works 40 Chapter 5 Create...

The Ultimate Next.js Ebook Index 00 Table Of Contents Chapter 1 Birth 01 Chapter 2 Introduction 07 Chapter 3 Roadmap 15 Chapter 4 How it works 40 Chapter 5 Create a Next.js Application 47 Chapter 6 Client Vs. Server 68 Chapter 7 Routing 87 Chapter 8 Rendering 115 Chapter 9 Data Fetching 126 Chapter 10 SEO and Metadata 141 Chapter 11 Backend 153 Chapter 12 Node vs Edge Runtime 166 Chapter 13 Server Actions 178 Chapter 14 Styling 192 Chapter 15 More of Next.js 199 Chapter 1 Birth In the first chapter, we explore the evolution of JavaScript and web development frameworks. We discuss the significance of embracing new technologies and compare code snippets in different frameworks to highlight their benefits. We introduce Next.js as a framework built on React.js, addressing limitations and incorporating new features. The chapter concludes with the recommendation to shift focus to Next.js for building modern web applications. Birth 01 Birth Not too long ago, in 2015, React.js entered the scene. However, even the journey of JavaScript in the IT industry hasn't been exceptionally long. Originally developed by Brenden Eich at Netscape in 1995, JavaScript gained significant popularity during the 2000s. This was largely due to Google's ingenious utilization of JavaScript to introduce interactive and dynamic features for map exploration. Subsequently, developers were introduced to frameworks and libraries, including jQuery, Angular, Node.js, React.js, and, most recently, Next.js. These technologies have revolutionized the web development landscape, offering developers various capabilities and possibilities. You might wonder why this information is relevant in the context. The significance lies in the fact that it highlights the timeless truth that "change is constant." As we continue to advance and evolve as a society, our tools and technologies will naturally progress alongside us. We have no other option but to embrace and adapt to these changes. It serves as a reminder that our willingness to embrace new ideas and technologies is essential for growth and success in the ever-changing IT industry landscape. These technologies and tools share a common purpose: to enhance work efficiency and improve performance. In this era, we can still use vanilla JavaScript or create websites using HTML and CSS without a doubt. Birth 02 However, when it comes to developing applications on a large scale, the efficiency of using the latest technologies surpasses that of traditional approaches. To showcase and experiment with this concept, we have created a video on "How to create a website using HTML & CSS" on our YouTube channel. You can personally analyze the amount of code and the level of efficiency demonstrated in the video. To provide a brief glimpse of the evolution in JavaScript coding practices, here is a well-known code snippet implemented in various frameworks, starting from the core JavaScript language itself — The Hello World: Vanilla JavaScript // HTML: Click Me document.getElementById('btn').addEventListener('click', function () { alert('Hello, World!'); }); jQuery // HTML: Click Me $('#btn').click(function () { alert('Hello, World!'); }); Birth 03 Angular import { Component } from '@angular/core'; @Component({ selector: 'app-example', template: `Click Me` }) export class ExampleComponent { showMessage(): void { alert("Hello, World!"); } } React.js import React from 'react'; class ExampleComponent extends React.Component { showMessage() { alert('Hello, World!'); } render() { return Click Me; } } “Ah? From what I see, there's an increase in the amount of code being written. It appears to be in complete opposition to what was mentioned earlier” — Are you thinking the same? If we look at it solely from this perspective, one would certainly feel that the original language and framework require less code. Birth 04 However, it's important to consider the bigger picture. And that's what truly matters, doesn't it? In reality, we don't just build "Hello World" projects. We undertake more substantial projects that demand the utilization of various frameworks and tools to achieve the desired functionality and scalability. We could have talked about the “big picture” of using React or even Angular over vanilla code, but that is not the primary focus of this eBook. However, it is worth mentioning a few foundational reasons why these new tools make development more efficient: Architecture — React and Angular follow a Component-Based Architecture, encouraging code reusability. For instance, if you create a component like a Button, you can use it anywhere in the application as often as needed. This reusability enhances the maintainability and scalability of the application. Virtual DOM — The Virtual DOM is a lightweight representation of the actual DOM. It facilitates efficient and optimized updates to the user interface, resulting in improved performance. Simply put, it tracks changes within the application and performs a "diffing" process by comparing the previous version of the virtual DOM with the new version. It identifies the differences and updates the real DOM accordingly. Ecosystem & Community — Modern libraries like React.js have vibrant and active communities. This provides developers with abundant resources, extensive documentation, reusable code packages, bug fixes, and support. Birth 05 … and many other libraries or framework-specific reasons that you can explore. To truly appreciate the impact, I would once again recommend visiting the YouTube videos we created, where you can experience firsthand what it takes to build a simple landing page using two different tools to measure the efficiency of these tools: Build and Deploy a Sushi Website using HTML & CSS Watch and Code Now Build and Deploy a Bank Website using React.js Watch and Code Now But hey, where does Next.js come in the picture? As mentioned earlier, as we continue to progress, technology also advances. jQuery addressed the limitations of vanilla JavaScript, and then React.js emerged to overcome the shortcomings and loopholes of jQuery. However, even React.js has its own challenges, which have now been addressed by another tool called Next.js. It’s a big misconception that Next.js is a new language or library. No! Birth 06 Vercel, the team behind Next.js, embarked on a unique approach to develop a framework encompassing client-side (frontend) and server- side (backend) functionalities within a single application. Guillermo Rauch, the original creator of Next.js and the mastermind behind Socket.IO, began working on this idea in 2016. Over the course of a year, they continuously added new features such as file-based routing, automatic code splitting, hybrid rendering, internationalization, image and font optimization, and many more. The relentless dedication of the Vercel developers, coupled with their ability to transform diverse ideas into reality, has caught the attention of Meta (previously known as Facebook) — the creators of React.js. Meta now explicitly recommends that developers use Next.js as their primary tool instead of relying solely on React.js. It's an extraordinary achievement! And that’s how we developers now need to shift our focus to the latest and greatest version, Next.js 15, to build highly capable and production- ready applications. This exciting evolution opens up new possibilities and opportunities for creating advanced web applications. Onto the next chapter… Chapter 2 Introduction In this chapter, we'll dive into Next.js, a flexible React framework. We'll explore its advantages over React.js, including simplified frontend development, reduced tooling time, and an easy learning curve. We'll also discuss how Next.js improves performance, enhances SEO, and keeps advancing with new features. By the end, you'll grasp the importance of mastering Next.js and be prepared to embark on an exciting journey with this framework. Introduction 07 Introduction Next.js — A flexible React Framework. But what does that mean? In software development, a framework serves as a tool equipped with predefined rules and conventions that offer a structured approach to constructing an application. It provides an environment that outlines the overall architecture, design patterns, and workflows, allowing developers to focus on implementing specific application logic rather than dealing with low-level design. Simply put, a framework provides pre-built solutions for common functionalities such as integrating databases, managing routing, handling authentication, and more. So what sets Next.js apart from React.js? — Next.js introduces plenty of features and capabilities that we will dive into in the upcoming chapter in detail. But what you need to understand is Next.js is essentially an extension of React.js, incorporating pre-built solutions, ready-to-use features, and some additional functionalities. In other words, Next.js is built on top of React, expanding its capabilities. If you’re already a React.js developer, the Next.js journey will be silky smooth. If you don’t know React.js, you should familiarize yourself with some of the main foundations of React.js, i.e., How to create a component, state management, code structure, etc. Introduction 08 To help you learn faster, we have a crash course on React.js that covers all the important things and includes a project for you to practice and test your skills: React.js Crash Course Watch and Code Now But Why should you use a React Framework — Next.js? React is constantly evolving and revolutionizing the way websites are built. It completely transforms your approach to designing and developing applications. It begins by encouraging you to think about components, breaking down the user interface into small pieces of code. You describe states to introduce interactivity and establish connections between these various components, shaping the flow of your application. Implementing the great React architecture requires deep integration between all parts of your application, and this is where frameworks come in: Less tooling time Every aspect of frontend development has seen innovation, from compiling, bundling, minifying, formatting, etc., to deploying and more. Introduction 09 With Next.js, we won’t have to worry about configuring these tools, thus investing more time in writing React code. We can focus more on business logic using open-source solutions for routing, data fetching, rendering, authentication, and more. Easy Learning Curve If you are familiar with React.js, you will discover Next.js is considerably simpler. Next.js, built on the foundation of React.js, offers exceptional documentation that provides comprehensive and detailed information on the why and how of using Next.js. The "Introduction | Learn Next.js" guide developed by the Vercel team is regarded as one of the best resources for the learning experience. The constant updates and help from the community make the development process even easier. One of the key aspects of Next.js is that it is not just a Frontend React Framework but a Full Stack React Framework enabling you to write backend code alongside your frontend code. How does it contribute to an "Easy Learning Curve"? Wouldn't it be another thing to learn? Absolutely not. The backend aspect of the code you'll be working with is much simpler than you might anticipate. There's no need to set up anything or configure any routes as we have to do for any traditional backend app. Introduction 10 In fact, the Vice President of Vercel, Lee Robinson, expressed the following viewpoint: Moving from React + Express + Webpack to a framework resulted in removing 20,000+ lines of code and 30+ dependencies – while improving HMR (Hot Module Reloading) from 1.3s to 131ms. If the backend and tooling aspects discussed here seem confusing, there's no need to worry. In the upcoming chapters, we will dive into a practical comparison of how things are done with React.js and Express.js, as well as how both can be accomplished within Next.js. Improved Performance Next.js offers built-in features like server-side rendering, static site generation, and automatic code splitting, which optimize application performance by enabling faster initial page loads, improving SEO, and enhancing the user experience. However, it doesn't mean server-side capabilities are limited to Next.js alone. React has introduced a new concept called React Server Components, which allows rendering components on the server side. So, why choose Next.js over using React alone? The advantage lies in the convenience and productivity provided by Next.js. By utilizing Next.js, you can leverage the existing features of React without the need for extensive setup and configuration. Introduction 11 Next.js automates many aspects, allowing you to focus more on utilizing the features rather than dealing with infrastructure & boilerplate code. This approach follows the principle of "Convention over Configuration," streamlining the development process and reducing the amount of code you need to write compared to implementing React Server Components independently. SEO - Search Engine Optimization Perhaps the most ignored and must topic in an application’s life, and the only drawback of React.js. The key difference lies in the rendering approach between Next.js and React.js. Search engine crawlers are like busy visitors to websites. They come and ask for the content of pages. They explore the links on those pages, carefully examining and organizing them for ranking purposes. This is what they do every day. To do their job well, they need to be able to access the content of the website pages. React.js renders everything on the client side, sending a minimal initial HTML response from the server. The server sends a minimal HTML file code and a JavaScript file that the browser executes to generate the HTML. This poses a challenge for search engine crawlers to access and understand the complete content of the page. On the other hand, Next.js provides the option of Static Site Generation (SSG) or Server Side Rendering (SSR). Introduction 11 With SSG or SSR, the server sends the complete HTML file and minimal JavaScript code to render only the content requiring client-side interaction. This enables search engine crawlers to access easily and index every page of the Next.js website accurately. But, now you might wonder, "Why should I prioritize SEO?" SEO is essential for making your website visible and highly ranked in search engine (browser) results. When you focus on SEO, you get several benefits, like more people visiting your website, better user experience, increased trust and credibility, and an advantage over your competitors because your website shows up higher in search results. Giving priority to SEO can greatly impact how well your website does and how many people find it online. Always Advancing Next.js, the ever-evolving framework, consistently introduces new features to simplify developers' lives. With over 7+ versions released last year, Next.js focuses on innovation and improvement for a better user experience. This is precisely what frameworks like Next.js aim to achieve, making development easier and more efficient. On top of that, other technologies like Expo, used for building React Native projects, are also adopting Next.js's groundbreaking features. Inspired by Next.js's file-based routing system, Expo developers have implemented a similar feature — Expo Router to improve the decade- old routing system in React Native. Introduction 12 Isn’t that great? Master one feature and effortlessly utilize it across multiple platforms However, the list of features provided by Next.js goes beyond what has been mentioned so far. It offers a wide range of capabilities, including seamless file-based routing, efficient code splitting, image & font optimization, HMR(Hot Module Replacement), API Routes(backend), built-in support for Sass, CSS modules, data fetching choice (SSG, SSR, ISR), error handling, Metadata API (For SEO), Internationalization(support for any spoken language), etc. It is best to try these features firsthand through practical implementation to truly appreciate its potential. That's precisely what we will do in the upcoming lessons – dive into the coding aspect! "Hmm, alright. I'm willing to trust your insights on the new features of Next.js and such. However, is it actually being used by people? Are companies actively seeking professionals with Next.js expertise? Is there a high demand for it in the industry?" — Are you wondering the same? Let the data speak for itself: Introduction 13 In the past 30 days, Next.js has received significantly higher search interest worldwide than React.js. But hey, that’s just a Google trend. What about the industry? Are people even creating websites using Next.js? Sure, let’s take a look at “The Next.js Showcase” which shows different companies using Next.js: Notio TE Futuris Hul Auth Material-U Netflix Job Product Hun Coco Col Nik Hyunda Ferrar HBO Ma Porsch Hashnod Audibl repl.i Verge Typeform Marvel Introduction 14 And many more renowned names. This demonstrates the genuine excitement and widespread adoption of Next.js! Considering the rapid rate at which companies embrace Next.js, it would be no surprise to witness a huge surge in demand for Next.js jobs in the coming months, if not years. Now is the perfect time to seize the opportunity and prepare for the future job market by mastering Next.js. With this book and the courses we have done and will continue to do, you can be the next Next.js developer. So, grab a cup of coffee, and let's get started on this exciting journey! Chapter 3 Roadmap The Roadmap is a concise guide to web development essentials. It covers HTML for structuring web content, CSS for styling and layout, and JavaScript for interactivity. Learners will grasp important concepts like semantic tags, visual effects, variables, control flow, functions, and manipulating the DOM. This chapter equips beginners with the skills needed to create dynamic and interactive web applications. Roadmap 15 Roadmap Before we start exploring Next.js, reviewing or relearning some basic concepts is a good idea to make learning easier. It all begins with building a solid foundation through fundamentals. Think of this roadmap as a summary of what you should know as a foundation for learning Next.js. It's alright if you're unfamiliar with advanced topics like integrating databases or implementing authentication. These points help you understand the main concepts without focusing on specific coding details. In Next.js, there are various approaches to implementing these concepts. You have options like utilizing NextAuth (one of the coolest features), exploring popular market solutions like Clerk, or even building everything from scratch. Similarly, when it comes to databases, you can choose between different options such as SQL databases like Postgres, NoSQL databases like MongoDB, or even consider using Prisma as an ORM (Object- Relational Mapping) manager. Whether or not you have coding experience is not the most important factor here. What truly matters is understanding the underlying concepts. The roadmap is designed to introduce you to these concepts and familiarize you with the beneficial knowledge when aspiring to become a Next.js Developer. Roadmap 16 Later in the next chapters, and with our branded courses, you’ll learn how to do all the code stuff in Next.js. So don’t worry; you have our back! Presenting the Roadmap, These points help you understand the main concepts without focusing on specific coding details. 1 Web Development Fundamentals HTML - HyperText Markup Language Basics Understand the structure, elements, and attributes of HTML documents Structure Elements Heading to Image Paragraph Input Lists Button Link Group Elements v> { console.log("I'm Client Component :)"); return ( This an example client component ); }; export default ExampleClient; Client Vs. Server 77 And the small ExampleServer component as components/ExampleServer.jsx const ExampleServer = () => { console.log("I'm Server Component :)"); return ( This is an example server component ); }; export default ExampleServer; Now, first import & use the ExampleClient component inside the app/ page.js file: app/page.js import styles from './page.module.css' import ExampleClient from '@/components/ExampleClient' export default function Home() { console.log("Where do I render?") return ( Welcome ) } Client Vs. Server 78 Perfect. Let’s check where we see which console log First browser, Create Next App http://localhost:3000 Okay, that’s right, right? We explicitly said Next.js to render ExampleClient.jsx as Client Component. Fair enough! Going back to the Terminal, we see… Terminal npm run dev - next dev - wait compiling /page (client and server)... - event compiled client and server successfully in 390 ms (418 modules) Where do I render? I'm Client Component :) Client Vs. Server 79 Both of them, why? This is because Next.js performs pre-rendering certain content before sending it back to the client. So basically, two things happen: Server Components are guaranteed to be only rendered on the serve On the other hand, client components are primarily rendered on the client side. However, Next.js also pre-renders them on the server to ensure a smooth user experience and improve search engine optimization (SEO). Next.js, by default, performs static rendering, which means it pre- renders the necessary content on the server before sending it to the client. This pre-rendering process includes server and client components that can be pre-rendered without compromising functionality. The server Component is the latest React.js Feature. Next.js has simply used it over what they had, making the setup easy. Let’s play around with these components a little more. Now, import the ExampleServer component inside the app/page.js file Client Vs. Server 80 app/page.js import styles from './page.module.css' import ExampleClient from '@/components/ExampleClient' import ExampleServer from '@/components/ExampleServer' export default function Home() { console.log("Where do I render?") return ( Welcome ) } And now, if we visit the browser, along with showing both client-server component text on the website, it’ll only show the “I'm Client Component :)” log inside the browser’s console: Create Next App http://localhost:3000 Client Vs. Server 81 Whereas the terminal will show all the three console logs Terminal npm run dev - next dev - wait compiling /page (client and server)... - event compiled client and server successfully in 588 ms (548 modules) Where do I render? I'm Server Component :) I'm Client Component :) All good! For the final play, let’s remove the ExampleServer from app/page.js and add it inside the components/ExampleClient.js app/page.js import styles from './page.module.css' import ExampleClient from '@/components/ExampleClient' export default function Home() { console.log("Where do I render?") return ( Welcome ) } Client Vs. Server 82 And the ExampleClient will look like this: components/ExampleClient.jsx "use client"; import ExampleServer from "./ExampleServer"; const ExampleClient = () => { console.log("I'm Client Component :)"); return ( This an example client component ); }; export default ExampleClient; Hit save and see the result in both the Terminal and Browser console. First, let’s see what the terminal shows: Terminal npm run dev - next dev - wait compiling /page (client and server)... - event compiled client and server successfully in 429 ms (549 modules) Where do I render? I'm Client Component :) I'm Server Component :) Client Vs. Server 83 As expected, we see all three console logs due to the pre-rendering of Next.js and the server feature. But something doesn’t look good in the Browser console… Create Next App http://localhost:3000 Why is the server component log appearing here? Wasn’t it supposed to be on the server side only? Well, in Next.js, there is a pattern at play. When we use "use client" in a file, all the other modules imported into that file, including child server components, are treated as part of the client module. Consider "use client" as a dividing line between the server and client code. Once you set this boundary, everything inside it becomes client code. Understood? If not, there is no need to worry. Cli nt V S rv r e s. e e 84 Just remember: Do not include server components inside the client components. And in case you encounter such a scenario, we have a solution. We'll discuss it in detail in its dedicated section, where we'll dive into the rendering process of client and server components. Additionally, we will share some valuable tips and tricks on creating different types of components depending on real-world examples. Before we dive into yet another feature of Next.js, take some time out to work on the below tasks to solidify your learning so far: Tasks Add “use client” inside the app/page.js file and see where the console logs are appearing: app/page.js "use client" import styles from './page.module.css' import ExampleClient from '@/components/ExampleClient' export default function Home() { console.log("Where do I render?") return ( Welcome ) } Client Vs. Server 85 What are the different types of components in Next.js, and explain their difference? What are the benefits of server-side rendering? What are the latest features of the app directory regarding the client/server rendering? Chapter 7 Routing In this chapter, you'll learn about routing in Next.js and how it simplifies the process compared to React.js. Next.js uses a file-based router system, where folders and files define routes and UI components, respectively. It covers creating a navigation bar component, organizing routes with folders, handling nested and dynamic routes, and leveraging Next.js' Fast Refresh feature. Overall, you'll gain a practical understanding of Next.js routing and its advantages. Routing 87 Routing Now, let’s dive into routing! One of Next.js’s cool features is its ability to handle routes out of the box. But before we jump into that, let's first understand how routes are created in React.js. Here's an example of how a route can be created using react-router- dom v6 in React.js: App.js import { BrowserRouter as Router, Route, Link, Routes } from 'react- router-dom'; const App = () => { return ( ); }; export default App; And here's a possible example of a nested dynamic routing for a multi- page website like an e-commerce site: Routing 88 App.js import React, { Fragment } from 'react'; import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; function App() { return ( ); } export default App; Scary, isn’t it? Not only do we need to download and handle an external package, but as our application gets bigger, the routing becomes more complicated, making it harder to manage and understand! Routing 89 Now, let's explore what Next.js brings to the table for routing Next.js, aiming to simplify the process, uses a “file-based” router system. Meaning, Folders are used to define route Files are used to create UI for that route segment For instance, to convert the previous React.js routing example into Next.js, we only need to create two folders named about and contact. We'll create a special file associated with that route segment inside each folder, such as page.js or page.jsx. Let’s understand it while we code. Quickly create a new Next.js app inside the NextEbook folder, like in the previous chapter. I'll name the application routing. Before we begin, let's clean up the existing code to make it more organized and easier to understand for this use case: Remove page.module.css completel Add the CSS properties for the main tag inside the globals.css file. Leave the remaining CSS code unchanged. Routing 90 app/globals.css main { padding: 2rem; display: flex; justify-content: center; align-items: center; flex-direction: column; } Remove the code inside app/page.js and keep only the main & h1 tag app/page.js export default function Home() { return ( Home ) } Make sure everything is working correctly. Now, let's create a simple navigation bar (Navbar) component to move between the different pages we'll create easily. Create a components folder inside the root of the application. Inside create two files Navbar.jsx and navbar.module.css Navbar.jsx — contains a simple navbar with few links. We’re using the Link component of next/link to navigate between the different routes of the application by providing the appropriate route path to the href. Routing 91 components/Navbar.jsx import Link from 'next/link'; import styles from './navbar.module.css'; const Navbar = () => { return ( Next.js Home About Contact ); }; export default Navbar; And create the corresponding style modules for the same i.e., navbar.module.css Routing 92 components/navbar.module.css.nav { width: 100%; padding: 1.5rem 2rem; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; border-bottom: 1px solid #2c2c2c; }.links { flex: 1; list-style: none; display: flex; justify-content: end; align-items: center; gap: 2rem; }.links li { white-space: nowrap; cursor: pointer; }.links li:hover,.links li:active { color: #0099ff; } Nothing too complex. To ensure that the navbar appears on all route pages, we have two options: Routing 93 The first option is importing the navbar component in each route page The second option is to import the navbar component in the parent component of these routes, such as layout.js. Importing it into the parent component will consistently display the navbar across all route pages. Wrong Method app/page.js import Navbar from '@/components/Navbar' export default function Home() { return ( Home ) } app/about/page.js import Navbar from '@/components/Navbar' export default function About() { return ( About ) } Routing 94 Right Method app/layout.js import './globals.css' import { Inter } from 'next/font/google' import Navbar from '@/components/Navbar' const inter = Inter({ subsets: ['latin'] }) export const metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children }) { return ( {children} ) } By now, if you have followed all the steps properly, you should see this inside your browser: Routing 95 Create Next App http://localhost:3000 Now is the routing time! Note: Please follow the Kebab Case writing convention when writing route names. After creating the folder with the name about, create the special UI file page.js inside it to show the UI for that route: app/about/page.js export default function page() { return ( Home ) } Routing 96 App About page.js Contact page.js page.js And what next? Well, that’s it! Go to your browser and click the "About " link in the Navbar. You will notice that the URL changes, and the text displayed on the page switch from "Home" to "About"! Routing 97 Create Next App http://localhost:3000 How easy is that? Especially compared to the React.js code we examined at the start! Go ahead and create the route for “Contact ” in the same way, i.e., Within the app directory, create a new folder called contact Inside the newly created contact folder, create a file named page.js Add the necessary code to the page.js file to display the desired text. app/contact/page.js export default function Contact() { return ( Contact ) } Routing 98 After saving the changes, return to the browser. You will notice that the modifications are immediately visible without reloading the page, all thanks to Next.js' Fast Refresh feature. Create Next App http://localhost:3000 Routing 99 That was all about creating a simple route in Next.js. But what about nested or dynamic routes? What do we have to do? Let’s explore Nested Routes It’s as simple as nesting one folder inside the other. For instance, we wish to set up a route named projects/list. To achieve this, we create two folders: projects and within it another folder called list. Inside the list folder, we add the page.js file containing the user interface (UI) for that specific route. app/projects/list/page.js export default function ProjectsList() { return ( ProjectsList ) } Routing 100 To simplify navigation to the Product List page, let's quickly include a Link tag within the Home page: app/projects/list/page.js import Link from "next/link"; export default function Home() { return ( Home See Projects ) } Now visit the home page, and you’ll see See Projects; clicking on this link will take you to the route we created, which is /projects/list. Create Next App http://localhost:3000 Routing 101 Simple nest folders within one another and create whatever route you want. Moving forward, we have, Dynamic Routes Think of it as nested routes but with a slight difference. Unlike traditional nested routes where we need to know the exact route name in advance, dynamic routes allow for more flexibility. The route is determined based on changing data in the application, so we don't need to predict it beforehand. For instance, if we need to show various project details, we can design a single details page with a consistent layout for all projects. The only difference will be some data that changes for each project. Instead of making separate routes for every project detail page, we can use a dynamic route of Next.js. To create a dynamic route, we’ll have to wrap the folder's name in square brackets, symbolizing that the content inside this square bracket is variable, i.e., [folder-name]. Continuing our current application, let's add a feature for displaying project details. Imagine we have three projects named jobit, carrent and hipnode. We need three routes to showcase these projects: /projects/jobit, /projects/carrent, and /projects/hipnode. Each route represents a different project, allowing us to show its details. We could create these as nested routes, but there are better ways. Routing 102 Imagine the number of folders you'd have to create if you're a professional developer with over 10 fantastic projects! And then, you'd have to keep copy-pasting the similar project details code. That's where dynamic routes come to the rescue! They provide a better solution for handling such scenarios. Within the existing projects folder, create a new folder with a name enclosed in square brackets, i.e., app/project/[slug]. I referred to it as slug to address the segment in general, but you can choose any name you prefer, like id or name. Additionally, create the corresponding special UI file, page.js, in the same location folder. app/projects/[slug]/page.js export default function ProjectDetails() { return ( Project Name ) } Routing 103 To access this route, we will include links to our hypothetical projects on the projects list page and give them a bit of styling. app/projects/list/page.js import Link from "next/link"; import styles from './projects.module.css' export default function ProjectsList() { return ( My Projects JobIt Car Rent hipnode ) } And corresponding relatively simple styles in the same folder: Routing 104 app/projects/list/projects.module.css.ul { margin-top: 2rem; list-style: none; display: flex; justify-content: center; align-items: center; flex-direction: column; gap: 1rem; width: 100%; }.ul li { padding: 1rem; width: 100%; max-width: 300px; border-radius: 10px; border: 1px solid #2c2c2c; text-align: center; cursor: pointer; } And corresponding relatively simple styles in the same folder: Routing 105 Is there anything else? Nope, that's all there is to it. Simply click on these project names and witness it in action! Create Next App http://localhost:3000 However, something doesn’t feel good. While the route for these projects changes correctly, it would be great to see the actual project name displayed on the respective route pages instead of the static "Project Name." So, how to do that? The [slug] part over here is our dynamic route segment. And Next.js provides a way to access what value has been passed to it via the params prop passed to page.js page. To utilize the value of this dynamic segment, we need to do this: Rout in g 106 app/projects/[slug]/page.js export default function ProjectDetails({ params }) { return ( Project {params.slug} ) } If you choose to use [id] or [name] instead of [slug] as the folder name, you will need to access it as params.id or params.name, respectively. Whichever name you provide, it will be the same name to access the value through the params object. Amazing, isn’t it? But that’s not the end of the routing in Next.js. Coming next are, Route Groups When working with a file-based system, having numerous folders within the app folder may be better, especially in a more complex system. To address this and offer better control over folder organization without impacting the URL path structure, Next.js introduced a feature called "Route Groups.” Need help to make sense of? Consider the existing structure: we already have three folders: about, contact, and projects. Routing 107 Now, if we need to add functionality like sign-in and sign-up, we would have to create more folders within the app folder, causing it to grow larger and larger. What if we could limit the number of folders inside the app folder to a maximum of 1-3 and include everything within these folders while maintaining the same route path? In this case, if we create these folders, i.e., auth and, let's say, dashboard, right away and add the corresponding folders & pages inside them, it will impact our routing. Why? Because, as we've learned, each folder name serves as a route name. app auth sign-in page.js sign-up page.js Routing 108 If we do it like the above, the route name for the sign-in page would be /auth/sign-in, and similarly, for the sign-up page, it would be /auth/ sign-up. We intended something else, right? Our desired route names are /sign-in and /sign-up, but we still want to maintain proper file organization. We don't want auth to be included in the URL, but we do want it to be present in our code structure. To meet this specific requirement, we have Route Groups. They help organize routes into logical groups like auth, team, etc. We can create a route group by enclosing the folder name in parentheses, like (auth). In this case, if we create these folders, i.e., auth and, let's say, dashboard, right away and add the corresponding folders & pages inside them, it will impact our routing. Why? Because, as we've learned, each folder name serves as a route name. (auth) Create the (auth) folder inside the app folder and add routes for the sign-in and sign-up pages. Additionally, create a page.js file within each of these folders to display the respective UI: Sign I Sign Up Routing 109 Sign In app/(auth)/sign-in/page.js export default function SignIn() { return ( Sign In ) } Sign Up app/(auth)/sign-up/page.js export default function SignUp() { return ( Sign Up ) } Here is how the structure should appear: Routing 110 Next, let's transfer the remaining folders, namely about, contact, and projects, into our (dashboard) route group. (dashboard) Create a folder named (dashboard) within the (app) folder and simply move the previously created folders (about, contact, and projects) into it as they are. app (auth) (dashboard) about page.js contact page.js projects [slug] page.js list page.js Your structure should now look like this: Routing 111 All set. Now let's put our application to the test How surreal! No code breaks, and everything works flawlessly — as if nothing had happened. The URL, the linking — everything is functioning perfectly, and all of this on the first try! Create Next App http://localhost:3000 Routing 112 Moreover, we can observe our newly created auth routes by modifying the URL, such as: Create Next App http://localhost:3000 That, my friend, is the beauty of Next.js 15! Is that the end? End of routing? Of course, not! There are two more amazing client-side routing features, i.e., Parallel Routes and Intercepting Routes. Not to forget, we also have API routes We will discuss the Parallel & Intercepting Routes in the “Advanced Routing” chapter with the suitable associated code example. But to warm you up: Routing 113 Parallel Routes This feature allows us to display one or more pages simultaneously or conditionally within the same layout. Let's imagine we're developing an e-commerce dashboard. Depending on the logged-in user, we need to render different UI components. For instance, if an admin is viewing the dashboard, we want to display complete sales data and the list of users and products. However, for non-admin users, we should show sales and products specific to them while hiding the list of users. All of this should be on the same route. Rather than complicating the code within a single page with multiple conditions, we can utilize parallel routes that render based on whether the user is an admin or not. Intercepting Routes This feature is handy when displaying a new route while preserving the current page's context. It allows us to intercept a new route without fully transitioning from the current layout. Now, let's consider a scenario where we're developing an e-commerce website and want to implement a product preview feature. When we click on the "Preview" button for a product, it should display limited information about the product in a modal format, and the URL should change to products/product-1. However, the modal should remain on top of the current page, just like a typical modal. This is where intercepting routes come in handy. Routing 114 We can utilize this feature to display the content inside the modal on top of the page from which it was triggered while also updating the URL to reflect the product previewed. We’ll fully dive into these two powerful features when creating an application in the upcoming advanced routing chapter. Tasks Create a complete routing structure for an e-commerce project using different routes. Here are the expected routes: Home page: "/ Product listing page: "/products Product detail page: "/products/{productId} Shopping cart page: "/cart Checkout page: "/checkout Order confirmation page: "/order/{orderId} User account page: "/account Login page: "/login Registration page: "/register Search results page: "/search?q={searchQuery}" Explore routing of Next.js. How does it differ from routes in React.js? What is the purpose of route groups, and how can they be created in Next.js? What is a dynamic route, and why should we create dynamic routes in web applications? Chapter 8 Rendering In this chapter, you'll learn about rendering in Next.js and gain a deep understanding of key concepts, strategies, and environments. You'll discover how Next.js handles rendering, the different rendering strategies it offers, and when to use each one. Rendering 115 Rendering We have previously discussed terms like "rendering," "runtime, and "environment," but what do they truly mean, and how does Next.js fit into the picture? You might be thinking, "Enough with the theory, show me the code!" Well, we can definitely do that. In fact, we have already done some best-in- class Next.js 15 project videos for you to dive right into. Build and Deploy a Full Stack Build and Deploy a Full Stack MERN Next.js Threads App... Next.js Application | React... Watch and Code Now Watch and Code Now Build and Deploy a Modern Next.js Next.js Full Course 2024 | Build Application | React, Next JS, Typ... and Deploy a Full Stack App... Watch and Code Now Watch and Code Now However, it's important to note that simply watching these videos and successfully deploying your application might not suffice. Rendering 116 When you eventually venture into your own projects, you might stumble because you lack a deep understanding of the "why" behind your decisions. You’ll find yourself struggling with the choice. So always aim to clear your “Why” and sit back to watch yourself perfecting the “How”! In Next.js 15, there are different ways things are displayed (strategies), the specific times they run (runtime/build time), and the specific places where they work (environment). Rendering It’s a process of generating or creating the user interface from the code we write. React 18 and Next.js 15 introduced different strategies to render an application. Believe it or not, we can use multiple strategies within the same application to render it differently — the god mode feature of Next.js! Although we did talk about it a bit, Environments There are two environments where we can render our application code, i.e., the client (User’s browser) and server (Computer where we deploy our code). Rendering 117 Client Server Rendering Process Occurs on the user’s browser Happens on the server before sending the page to the client’s browser Interactivity & Provides a dynamic and Provides a fully rendered Load Time interactive user experience HTML page to the client resulting in faster initial page load time Fetching & SEO Smoother transition between Fully rendered content the pages and real-time enhancing search engine data fetching rankings and social media sharing previews Load & Reduced server load and Performs well on any slower Per f ormance potentially lower hosting device as rendering is done costs as the client’s browser on the server is responsible for handling the rendering. Consistent Compatibility and Consistent rendering across Rendering performance depend on the any devices regardless of user’s device configuration. the configuration reducing the risk of compatibility issues Sec u rity Potential risk of security Reduces the amount of vulnerabilities such as client-side JavaScript code Cross-Site Scripting (XSS), sent to user’s browser thus Code Injection, Data enhancing security by Exposure, etc. limiting potential vulnerabilities So which to use and when? Rendering 118 If search engine optimization (SEO), security concerns, and user device specifications are not a priority for you, and your focus is primarily on delivering dynamic interactivity to the user, then client-side rendering (CSR) with technologies like React.js can be a suitable choice. A use case where this approach is applicable is in the business-to- business (B2B) domain. In such cases, the target audience is specific and known, eliminating the need to prioritize SEO since the product is not intended for a wide public audience. This allows you to prioritize developing interactive features and functionalities without dedicating significant resources to SEO optimization. And if you’re someone who cares about all these points, well, you know what to choose The time Once the compilation process is complete, which involves converting code from a higher-level programming language to a lower-level representation (binary code), our application goes through two crucial phases: Build Time and Run Time. Build time It’s a series of steps where we prepare our application code for production involving the steps of code compilation, bundling, optimization, etc. In short, build time or compile time is the time period in which we, the developer, is compiling the code. Rendering 119 Remember the npm run dev script? It’s that command that generated the build of our application containing all the necessary static files, bundling, optimization, dependency resolution, etc. Run Time It refers to the time period when the compiled or deployed application is actively executing and running, involving the dynamic execution of the application’s code and utilization of system resources. In short, run time is the time period when a user is running our application’s piece of code. It’s about handling user interaction, such as user input, responding to events, to data processing, such as manipulating/accessing data and interacting with external services or APIs. Run Time Environment Don’t confuse this with the “Run Time” we talked about just before. That was the time period of an application. Whereas RTE, run time environment, is a specific environment in which a program or application runs during its execution. It provides a set of libraries, services, or runtime components that support the execution of the program. The Node.js — What is it? Rendering 120 It’s a JavaScript Run Time Environment that allows us, developers, to run JavaScript code outside of the web browser. Similarly, Next.js provides two different run time environments to execute our applications’ code. The Node.js runtime Default runtime that has access to all Node.js APIs and the ecosystem The Edge runtime A lightweight runtime based on Web APIs with support to a limited subset of Node.js APIs. Next.js offers the flexibility of choosing the runtime. You can do switch swiftly by changing one word: export const runtime = 'edge' // 'nodejs' (default) | 'edge' Isn't it amazing? Just with a simple word change, a whole new ecosystem emerges. It's like the snap of Thanos's fingers, and suddenly, a completely different world opens up! Rendering 121 And for the final, Rendering Strategies Depending on the above-discussed factors, such as the rendering environment, and the time period, i.e., build and run time, Next.js provides three strategies for rendering on the server: Static Site Generation Remember the build time? Well, the famous SSG, static site generation, happens at build time on the server. During the build process, the content is generated and converted into HTML, CSS, and JavaScript files. It doesn’t require server interaction during runtime. The generated static files can be hosted on content delivery network (CDN) and then served to the client as-is. The result, the rendered content, is cached and reused on subsequent requests leading to fast content delivery and less server load. This minimal processing results in higher performance. Although SSG handles dynamic data during the build process, it requires a rebuild if you update anything, as it happens during the build time! An example use case would be any Documentation or Blog & News websites. All the articles or content are static 90% of the time. It doesn’t need any processing. Once built, we can ship it as it is. Whenever we want to update the content, we can rebuild it! Rendering 122 To address this limitation, Next.js introduced, Incremental Static Generation It allows us to update these static pages after we build them without needing to rebuild the entire site. The on-demand generation of ISR allows us to generate a specific page on-demand or in response to a user’s request. Meaning, a certain part of the websites or pages will be rendered at build time while other is generated only when needed, i.e., at run time. This reduces the build time and improves the overall performance of the website by updating only requested pages for regeneration. With this hybrid strategy, we now have the flexibility to manage content updates. We can cache the static content as well as revalidate them if needed. An example use case would be the same where we can use SSG for the article details page and use ISG for showing a list of articles And last but not least, Server Side Rendering Dynamic rendering, in a nutshell, enables the generation of dynamic content for each request, providing fresh and interactive experiences. If we have SSG and ISG, why do we need SSR? Rendering 123 Given the availability of Static Site Generation (SSG) and Incremental Static Generation (ISG), one might wonder why Server Side Rendering (SSR) is still needed. Both approaches offer valuable benefits, but their suitability depends on specific use cases. SSR excels in situations where a website heavily relies on client-side interactivity and requires real-time updates. It is particularly well-suited for authentication, real-time collaborative applications such as chat platforms, editing tools, and video streaming services. SSR involves heavy server-side processing, where the server executes code for every individual request, generates the necessary HTML, and delivers the response along with the required JavaScript code for client-side interactivity. Due to this dynamic nature, caching content responses becomes challenging, resulting in increased server load when compared to SSG or ISG. However, the benefits of real-time interactivity and up-to-date content make SSR a valuable choice for specific application requirements. But hey, we have the freedom to choose any of these rendering techniques for any part of your page code! Yes, you read that right. By default, Next.js uses Static Site Generation rendering. However, we can easily switch to Incremental Static Generation or Server Side Rendering as per our specific requirements for different parts of your application. The flexibility of Next.js allows us to pick the most suitable rendering approach for each page of our website. Rendering 124 Okay, okay, but when to use which method? Will this page or content display the same information for each request? Yes No? Static Site Generation Proceed to the next (SSG) is the suitable choice question. Does this page or content require frequent information updates, potentially every second? Yes No Server Side Rendering (SSR) Incremental Static is the appropriate option. Generation (ISG) is the recommended approach. That wraps it up, my friend. By understanding what it is and when to utilize it, we can make informed decisions that will impress our managers and bosses. The how of all this is following in the next chapter, so keep reading. But before you go, as usual, pause and try to answer these questions: Rendering 125 Tasks What does rendering mean? Explain different rendering strategies of Next.js What is build time and run time? Explain the difference between them in a Web application life What are the benefits of rendering content in a Client vs Server environment? Imagine, you are developing a large-scale e-commerce platform that requires a rendering strategy to handle a high volume of product listings. The platform needs to display product information, pricing, availability, and customer reviews. Additionally, the platform aims to provide a fast and interactive user experience. Considering the complex requirements of the e-commerce platform, discuss the trade-offs and factors you would consider when choosing between Static Site Generation (SSG) and Server Side Rendering (SSR) as the primary rendering strategy. Chapter 9 Data Fetching This chapter explores data fetching strategies in Next.js. We'll compare React's traditional hooks with Next.js' React Server Components (RSC) for efficient API and database interactions. Learn about Next.js' caching methods and rendering strategies like SSG, SSR, and ISR to enhance performance and data reliability in your applications. Data Fetching 126 Data Fetching Earlier, we explored various rendering environments and strategies, enabling us to determine the optimal approach for maximizing our app's performance in different scenarios. But how do we actually use these strategies in code? It's easy. The hard part was understanding how these different strategies work. So, let’s begin. Typically, if someone asks you to implement data fetching in an app, this is likely what you'd do, right? App.js import React, { useState, useEffect } from 'react'; function App() { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); setData(jsonData); } catch (error) { setError(error); } finally { setIsLoading(false); } }; fetchData(); }, []); Data Fetching 127 if (isLoading) { return Loading...; } if (error) { return Error: {error.message}; } return ( Data from API: {JSON.stringify(data, null, 2)} ); } export default App; Yep, it's the usual fetch using useEffect, where we call the API when the component mounts, retrieve the data, store it in the state, and then display it. But the same thing, with RSC — React Server Components in Next.js would look like this, import React from 'react'; async function App() { const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; Data Fetching 128 Isn’t it simple? Less code? And straight to the point? With React Server Components, we directly do fetch or any operations that we want to do without any need for hooks. For example, if we want to make a call to our database and get a list of items, we can do this in RSC, import React from 'react'; import prisma from './prisma'; async function App() { const users = await prisma.user.findMany(); return ( Data from Prisma: {JSON.stringify(users, null, 2)} ); } export default App; We know JavaScript follows sequential order. It starts from the top to bottom and executes each line depending on whether it’s synchronous or asynchronous in behavior. Here’s a general overview of how JavaScript execution works: Parsing: The JavaScript engine parses the entire script to understand its syntax. This involves breaking down the code into tokens and creating an Abstract Syntax Tree (AST). Data Fetching 129 Execution Context Creation: Before executing any code, the engine creates a global execution context. This context includes the global object (window in browsers, global in Node.js), the this keyword (which refers to the global object in the global context), and a reference to the outer environment. Hoisting: Variable and function declarations are hoisted to the top of their respective scopes. This means that they are processed before the execution of the code starts. Execution Phase: The code is executed line by line, starting from the top of the script. Each statement is executed in order unless it involves asynchronous operations. Asynchronous Operations: When encountering asynchronous operations like timers (setTimeout, setInterval), AJAX requests, or event listeners, JavaScript doesn't wait for them to complete. Instead, it continues executing the rest of the code. Once the asynchronous operation is complete, a callback function is added to the event queue. Event Loop and Callback Queue: JavaScript runtime maintains an event loop that continuously checks the call stack and the callback queue. If the call stack is empty, it takes the first callback from the queue and pushes it onto the call stack for execution. Function Execution : When a function is called, a new execution context is created for that function, which follows the same steps as the global execution context. Data Fetching 130 Function execution contexts are pushed onto the call stack, and when a function returns, its context is popped off the stack. Scope Chain: During execution, JavaScript resolves variable and function references by traversing the scope chain, which includes the local scope, the outer (enclosing) function scopes, and finally the global scope. Garbage Collection: As the code executes, the JavaScript engine keeps track of objects and variables no longer in use. These are marked for garbage collection to free up memory. For the above code, JavaScript will do the same (of course, Next.js & React.js will act first to execute code to turn this component into vanilla JavaScript), but where? Any guess? Of course, you know. On Server!! By default, any kind of components you’ll write in Next.js are React Server Components which are guaranteed to run only on Server. Then how can we write components that run on a client in Next.js? As easy, okay, I really need to stop doing that. We do so by adding a flag at the top of that component file, like this, Data Fetching 131 App.js 'use client'; import React, { useState, useEffect } from 'react'; function App() { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); setData(jsonData); } catch (error) { setError(error); } finally { setIsLoading(false); } }; fetchData(); }, []); if (isLoading) { return Loading...; } if (error) { return Error: {error.message}; } return ( Data from API: {JSON.stringify(data, null, 2)} ); } export default App; Data Fetching 132 Isn’t it too good? We can change the rendering execution environment just by adding/removing a two-word flag for each component in Next.js. I know, I know. But are you aware that what we've essentially done above is implement one of the rendering strategies of Next.js? Absolutely, it's SSG (Static Site Generation), the default rendering strategy used by Next.js. As we've previously covered, this strategy involves rendering the component on the server side during build time. Subsequently, whenever a user requests this specific component or page, the pre- generated static content is served to the user. It's cached and doesn't undergo re-rendering with each request, distinguishing it from other approaches. Alright, I see you understand now. But what if we need to refresh or reprocess the component or content every time a user sends a request? Yes, how do we implement the SSR strategy? Server Side Rendering Simple. Yes, I know I said it again, but it really is as simple as flipping a light switch. There are two ways to do this: Data Fetching 133 1. On Demand We can explicitly tell Next.js not to cache anything and thus render content on each request to get fresh data import React from 'react'; async function App() { const response = await fetch('https://api.example.com/data', { cache: 'no-store', }); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; cache has two values, no-store: With "no-store," Next.js skips checking its cache memory altogether. Instead, it goes straight to the main server every single time you ask for something. Plus, it doesn't save anything it downloads, so there's no chance of using cached data later on. force-cache: When setting the cache value to this, Next.js checks if it already has the information we're asking for stored in its memory. If it does and it's still up-to-date, it'll just give us that info without bothering anyone else. But if it doesn't have what we need, or if what it has is outdated, it'll go out and get the latest version from the main server, then save that updated info as a cache for next time. Data Fetching 134 There are additional methods, such as revalidatePath or revalidateTag, for on-demand validation, but we'll dive into those later in the "Server Actions" chapter. 2. Time based The whole basis of these rendering strategies is to cache the data depending on time. We know that by default, Next.js uses SSG, which caches everything. So what if we define this method at the time we want? Means, revalidate the cache whenever we want to. And how do we do that? As simple as… Yes, I know, another analogy. But it’s really that simple. We do it by adding this statement on the page, export const revalidate = false | 0 | number; or if we’re using fetch API, we do it so by, fetch(`https://...`, { next: { revalidate: false | 0 | number } }); Data Fetching 135 Do keep in mind that the fetch we’re using here isn’t the actual Web API Fetch. It has been extended by Next.js to automatically cache requests. It’s an extension to the original fetch API. So if you see someone using fetch in Next.js applications instead of axios or other, then it’s there for some reason. Did you read the above callout? Don’t skip it Back to the revalidate, it accepts different values, false: Means, as you expected, the resource will be stored in the cache for as long as possible, basically forever. It's like saying "keep this forever" to Next.js. But “forever” may not always work (like the real world). Although Next.js will keep the cache, HTTP cache might decide to get rid of older stuff eventually to make room for new things. The HTTP cache is a mechanism used by web browsers and servers to store previously accessed web resources, such as HTML pages, images, CSS files, and JavaScript files. When we visit a website, our browser may store copies of these resources locally on our device to speed up future visits. This caching helps reduce load times and bandwidth usage by retrieving files from the local cache rather than downloading them again from the web server. One more thing, revalidate=false is the same as revalidate=Infinity. Different ways of achieving the same thing. Data Fetching 136 0: It’s similar to setting revalidate to false. Same effect. It’ll tell Next.js not to cache anything and render that specific page/route every time the user makes a request/visit number: Choosing a certain number tells Next.js how long to keep a page or route in its memory (cache) before refreshing it. For example, if we set it to 5 minutes, Next.js will remember and show the same page for 5 minutes. After that, it will get a fresh version, save it, and repeat the loop. Understand? Does that remind you of something?? Think!! Now moving to where we were actually, i.e., Server Side Rendering. So can you now give me an example of how we can do SSR with time- based validation? Yes, we can implement SSR like this, import React from 'react'; async function App() { const response = await fetch ('https://api.example.com/data', { next: { revalidate: 0 }, }); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; Data Fetching 137 And yes, that way too, import React from 'react'; export const revalidate = 0; async function App() { const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; Amazing, both answers are absolutely correct to render a page every time a user makes a request! Upcoming, Incremental Static Regeneration Do you remember what and how ISR works?? We actually learned about it in SSR too. Take a pause, answer it to yourself, and then keep reading. When we want to make the most of both SSG and SSR, we do ISR. For example, for blogging applications. And a way to implement that in Next.js is like this, Data Fetching 138 import React from 'react'; export const revalidate = 5000; // (seconds) async function App() { const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; And if we just want to implement ISR only for a particular fetch, we do, import React from 'react'; async function App() { const response = await fetch('https://api.example.com/data', { next: { revalidate: 5000 }, }); const jsonData = await response.json(); return ( Data from API: {JSON.stringify(jsonData, null, 2)} ); } export default App; Easy peasy, isn’t it?? Data Fetching 139 Time to revise what you learned in this chapter. Take a pause and answer these questions. Tasks What are the methods for fetching data in Next.js? Explain the implementation of SSG, ISR, and SSR in Next.js with examples for each. What is the process for data revalidation in Next.js? Define the distinction between Time-Based and On-Demand Validation Explain the difference between these two examples and when we should use which. Scenario 1 import React from "react"; async function App() { const data = await fetch("https://api.example.com/data", { next: { revalidate: 5000 } } ); const dataJSON = await data.json(); const users = await fetch(https://api.example.com/users") const usersJSON = await users.json() return ( Data from API: {JSON.stringify(dataJSON, null, 2)} Users from API: {JSON.stringify(usersJSON, null, 2)} ); } export default App; Data Fetching 140 Scenario 2 import React from "react"; export const revalidate = 5000 async function App() { const data = await fetch("https://api.example.com/data"); const dataJSON = await data.json(); const users = await fetch(https://api.example.com/users") const usersJSON = await users.json() return ( Data from API: {JSON.stringify(dataJSON, null, 2)} Users from API: {JSON.stringify(usersJSON, null, 2)} ); } export default App; Chapter 10 SEO and Metadata This chapter explores SEO (Search Engine Optimization) in Next.js, focusing on enhancing website visibility and attracting organic traffic. Learn about implementing metadata for better search engine indexing, distinguishing between static and dynamic metadata, and leveraging Next.js features for optimized SEO strategies. SEO and Metadata 141 SEO and Metadata We talked about lots of things so far, from how Next.js works to different strategies, their implementation, and all. One of the highlighted parts of Next.js we talked about how it’s useful when it comes to “SEO” Using all these features we learned is amazing, but if we people don’t see it, then there is no use for it, is it? We build websites for people. So it’s also our responsibility to find a solution in such a way that we’ll get lots of traffic on our website and it’s noticeable by people on a seaful of websites internet. There are many ways to do that via the “non-developer” way. Meaning, your company or your team can create ads, funny memes, or create lots of social content, stay active, and all those. But this is non-organic traffic, meaning you have to pay some to get some traffic. On the other hand, organic traffic is what we as developers can do inside our code so web crawlers would be able to index them properly on search engines aka SEO — Search Engine Optimization. SEO is like trying to impress a picky cat with your website. Imagine your cat is internet, and it only pays attention to the shiniest, most interesting toys (websites). So, SEO is your way of making your website the coolest, sparkliest cat toy in the room—using the right tricks (keywords), arranging things neatly (site structure), and making sure your cat enjoys playing with it (user experience). SEO and Metadata 142 The better you do this, the more your cat (search engine) will show off your awesome toy to others (users). We can improve SEO by following these best practices on our website, Best Practices to Improve SEO Keywords Keywords are like labels that tell web crawlers what your content is about. When a user searches for something using these words, the crawlers know to present your page as a potential match. Content Quality High-quality content is like a magnet for both users and crawlers. Users stick around longer, and crawlers recognize that engagement, interpreting it as a signal that your content is relevant. Meta Tags Think of meta tags as your page's ID card. It tells search engines and users a quick summary of what to expect. A convincing ID card means more clicks. Website Structure Imagine your website is a book. A well-organized structure is like chapters and headings, making it easy for search engines to read and understand what's inside. SEO and Metadata 143 Site Speed Faster websites are like express lanes. Search engines love it because they can quickly check and list your pages. Users love it because they don't have to wait. And that’s what we learned so far throughout this ebook on how using RSC and SSR combined in Next.js gives us the best website performance. Backlinks Backlinks are recommendations. When other reputable sites link to yours, it's like saying, "This site is trustworthy." Search engines notice and boost your ranking. Clear URLs URLs are like street addresses. Clear ones make it easy for search engines to find your pages. Confusing addresses may lead to lost visitors. … and a few more. But now let’s see how we can actually implement some of these easily in Next.js. There are two ways through which we can add metadata to our website using Next.js’s Metadata API that decides the look & feel of our website when sharing with others or on the Internet in general (for search engines) But before that, we need to address the difference between static and dynamic metadata. Do you know the difference between them? SEO and Metadata 144 Static Metadata Simply put, it’s information that doesn't change very often, if at all. This includes things like the page title, meta description, and meta keywords. Once set, these elements remain the same unless intentionally updated by a website owner or developer. It's like writing your name on a label that's stuck on a box - it's there to stay unless you physically change it. Dynamic Metadata As you can guess, it’s information that can change based on various factors like user interactions, search queries, or other conditions. This type of metadata is often generated automatically by a website's content management system (CMS) or scripting languages. For instance, the meta description might change depending on the specific search term a user uses or based on the content of the page. It's like a label that updates itself depending on what's inside the box or who's looking at it. Understood? Now in Next.js, we can implement both of these using two different methods, SEO and Metadata 145 1. Config Based All we have to do is create a javascript object in any layout or page file and export it. Next.js will automatically detect it and turn it into relevant meta tags for those routes layout.tsx | page.tsx export const metadata = { title: 'JS Mastery', description: "Gain Real-world Experience And Land That Dev Job You've Always Imagined", }; export default function Page() {} The title key within this metadata object will be transformed into the HTML tag, while the description will be converted into a tag within the section of the HTML document. The result of the above code will be as follows, Output JS Mastery SEO and Metadata 146 Next.js gives us many ways to make our website better for search engines. It covers everything from setting up metadata for social media to organizing bookmarks and categories. You can check the complete metadata fields list here: Metadata Object and generateMetadata Options Link to blog This covered setting up static metadata using config-based approach, but how can we apply the same configuration approach to generate dynamic metadata, and when is it most appropriate to do so? Dynamic Metadata If there are dynamically generated pages, i.e., dynamic routes, that we want search engines to index—which is a best practice—we can use the generateMetadata function in Next.js to produce metadata specifically tailored for these pages. For example, to show you, I have implemented this strategy on my JS Mastery website for Resources. Free Resources | JS Mastery Free resources database containing ebooks, guides and videos https://www.jsmastery.pro/resources SEO and Metadata 147 For the main Resource page, you’ll see different titles and descriptions and if now you click on one of the resources, you’ll see a change in title and description as well. Free Resources | JS Mastery Free resources database containing ebooks, guides and videos https://jsmastery.pro/resource/1e Same for other resources. Each has its own title, description, and image, which helps web crawlers index these pages as well. Okay, but how can we achieve this in Next.js? Achieving this is super easy, and it’s like this: SEO and Metadata 148 layout.tsx | page.tsx export async function generateMetadata({ params }) { const { id } = params; const resource = await getResourceById({ id }); const title = resource.title + ' | JS Mastery'; const seoDescription = 'Free resources database containing ebooks, guides and videos'; return { title, description: seoDescription, other: { 'og:title': title, 'og:description': seoDescription, 'og:image': resource.image, 'twitter:title': title, 'twitter:image': resource.image, 'twitter:description': seoDescription, }, }; } export default function Page({ params, searchParams }) {} The og: and twitter: fields in metadata are used for social media optimization (SMO). They provide information to social media platforms like Facebook and Twitter about how shared links from your website should be displayed. og:: These are Open Graph meta tags, which are used by Facebook and other platforms to understand and display shared content. Examples include og:title, og:description, and og:image. These tags help control how your content appears when shared on social media platforms. SEO and Metadata 149 twitter:: These meta tags are specifically for Twitter cards, which allow you to control how your content is displayed when shared on Twitter. Examples include twitter:title, twitter:description, and twitter:image. Prior to defining the Page component, we gather metadata by fetching data from a database, API, or any other source. We then use this data to create the metadata object, and that's all. Some of you who have taken our Next.js course may have a question: What happens if we make a fetch or database call in the generateMetadata function and another one in the main component to display the result? Wouldn't this result in two fetch or database calls for the same thing? Excellent question, but the short answer is No, Nada, Nah. As we covered in the previous lesson, fetch requests are automatically memoized by default. This isn't the standard Web Fetch; it's an extended version that caches requests across the application. So, these fetch requests are automatically memoized for the same data across generateMetadata, generateStaticParams, Layouts, Pages, and Server Components. But, What if we don’t use fetch? We have alternative methods available, such as React’s Cache or Next.js’s unstable_cache, to achieve a similar result as Next.js’s fetch and avoid calling the database or API twice on the same page. SEO and Metadata 150 Does this make sense? Before we learn about the next strategy to add metadata in Next.js, do keep in mind that, “Both static and dynamic metadata through generateMetadata are only supported in Server Components.” Don’t try that in Client Component and expect it to work :D So, the next way of handling metadata in Next.js is — 2. File Based Metadata As the name suggests, we can put files like robot, sitemap, favicon, open graph images, or other site icons directly inside the app folder, and next.js will automatically detect and generate the corresponding meta tags. For example, > ap favicon.ic icon.(ico|jpg|jpeg|png|svg apple-icon.(jpg|jpeg|png opengraph-image.(jpg|jpeg|png|gif twitter-image.(jpg|jpeg|png|gif opengraph-image.alt.tx twitter-image.alt.tx... SEO and Metadata 151 It’s just about adding files with these names (has to be the same name) directly inside the app folder. It’ll work out the same as the config-based approach. You can find the full list of all files that can be created to define metadata here: File Conventions: Metadata Files | Next.js Link to blog One thing worth noting here is, file based metadata has the higher priority and will override any config-based metadata. So if you set metadata in a file, it will be used instead of the same metadata field you set in the configuration. So, can you now create proper SEOized applications using Nextjs? Before we dive into another interesting topic, take your time to complete these, Tasks Explain the concept of search engine optimization (SEO) and its
 importance in web development. How can we implement SEO in Next.js applications? How does metadata impact search engine rankings and visibility of web pages? SEO and Metadata 152 What are different strategies to define metadata in Next.js? Imagine you're hired by an online retailer that uses Next.js for their website. The company wants to improve its product pages' visibility in search engine results to drive more organic traffic and increase sales. How would you approach optimizing the product pages for SEO, considering factors such as product descriptions, images, and reviews? Chapter 11 Backend In this chapter, we dive into backend development using Next.js, exploring its modern approach to server-side operations and API handling. You’ll discover how Next.js simplifies backend tasks traditionally managed with frameworks like Express.js. Learn about setting up APIs with minimal configuration, implementing middleware for request processing, and leveraging Next.js features like dynamic routes and caching. Backend 153 Backend Having reached this point, perhaps some of you may have thought, 'Ah, I've had my fill of Frontend!' Using all these features we learned is amazing, but if we people don’t see it, then there is no use for it, is it? I don't need to say how important it is to know about developing websites that look good if you can make awesome sites like these using the newest Next.js, even if you're half asleep. Then even Devin can do better than you! Let's get back to what's important. Frontend is necessary, but so is the backend. Neither is better than the other (although I personally prefer frontend). They work toget

Use Quizgecko on...
Browser
Browser