ProNextJS
    Loading
    lesson

    Choosing a SSR Framework or a SPA System

    Jack HerringtonJack Herrington

    A common question is "Should I use Next.js or React?", which is interesting considering that Next.js is built on top of React.

    To clear up this confusion, let's look at the key differences between using a server-side rendered framework like Next.js and a single-page application (SPA) system like React with Vite or Create React App.

    Comparing Next.js and Vite Applications

    To illustrate the differences, let's take a look at two versions of the same application: one built with Next.js and the other with Vite.

    The Next.js application is on port 3000, and the Vite application is on port 5173.

    Next.js and Vite running side by side

    At first glance, they may look identical, but there's a significant difference under the hood.

    Disabling JavaScript

    To showcase the differences, we'll disable JavaScript in both applications using the developer tools. Here's how you can do it:

    1. Open the developer tools in your browser.
    2. Press Command + Shift + P (or Ctrl + Shift + P on Windows).
    3. Type "JavaScript" and select the option to disable JavaScript.

    After disabling JavaScript and refreshing both applications, you'll notice a striking difference:

    JS disabled

    The Next.js application still shows the content, as it's server-side rendered and the HTML is already present in the page.

    In contrast, the Vite application displays a blank page because it relies on JavaScript to run the React application.

    Examining the Page Source

    Let's take a closer look at the page source of both applications:

    side by side source code

    The Next.js application has a significantly larger page source compared to the Vite application, containing HTML from the start.

    When you make a request to the Next.js server, it performs the following steps:

    1. Runs the application on the server.
    2. Generates the HTML.
    3. Sends the HTML to the client along with a script tag containing the React code bundle.

    The React code is then executed on the client and hydrated, syncing the server-rendered HTML with the client-side application. This approach ensures that the user sees content on the screen quickly, which is beneficial for both the user experience and search engine optimization (SEO).

    On the other hand, the Vite application has a simple structure with a div containing an ID of "root" and a script tag bringing in the application source:

    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
    

    When JS is enabled, the client brings in the source for the application, mounts it onto the root component, and renders the application on the client-side.

    SEO Considerations

    Search engines like Google analyze the HTML output of servers to determine the content of a webpage. While there are varying opinions on whether search engines execute client-side JavaScript, many SEO experts recommend server-side rendering to ensure that the desired HTML is directly sent to search engine bots.

    By server-side rendering your application, you provide search engines with the complete HTML content, rather than relying on them to execute JavaScript to render the page.

    Understanding Client Components in Next.js

    In Next.js, you can create client components that allow for interactivity on the client-side. Let's create a simple example to demonstrate how client components work:

    "use client"
    
    export default function ClientComponent() {
      return <div>HELLO FROM THE CLIENT</div>
    }
    

    The 'use client' directive at the top of the file ensures that the component runs on both the client and the server.

    We can then import the ClientComponent in the page.tsx file:

    import ClientComponent from "./ClientComponent"
    
    export default function Home() {
      return (
        <main className="p-5">
          <h1 className="text-4xl font-bold">Welcome to GPT Chat</h1>
          <ClientComponent />
        </main>
      )
    }
    

    After importing and using the ClientComponent in your application, you'll see the message rendered on the page:

    the client component loads

    Looking at the source of the page, the rendered HTML from the server includes the content of the client component:

    This demonstrates that client components in Next.js run on both the client and the server, contrary to the common misconception that they only run on the client-side.

    With this misconception cleared up, let's continue on with adding authorization to the app.

    Transcript

    Now that we've got our Next.js application all laid out, I get to answer the one question that I get the most often when it comes to Next.js, and that's whether I should use Next.js or React to build my application, which is an odd question, because Next.js is built on top of React. So I think the question is actually whether I should use a server-side rendered framework like Next.js or Remix or Redwood or Waku versus using a SPA system or a single page application system like VEET or Create React App with React on top of that. So in order to really show the differences between those two, I've created a VEET application version of our application. Now can you tell which one is which? Well, if you look at the port numbers on the URL, it's a clue to which one is which.

    On the left-hand side, it's port 3000, which is our Next.js application, and on the right-hand side, it's port 5173, which is the standard Vite port. But otherwise, they look exactly the same, but there is a huge difference. Let me show you. So I'm going to bring up the developer tools on both of these. And then in both of these, I'm going to disable JavaScript by first doing Command-Shift-P, typing Java, and then disabling JavaScript.

    All right, cool. I'm going to refresh both. So refresh the Vite application first, and then I'll refresh our application. So big difference between those two. If I refresh the application on Vite, because there's no JavaScript running, it can't actually run our JavaScript code, which is our React application.

    So what we're left with is a blank page. Whereas in our Next.js application, because we've server-side rendered that, the HTML is actually in the page already. The only thing that isn't running is any JavaScript on the client, so we can't be interactive, but everything else will still be there in terms of the content. To bring this home even more, let's take a look at the page source for these applications. So again, on the left-hand side, we have our Next.js application, which is clearly significantly larger than our Vite application, which is on the right-hand side.

    Now, our Vite application is pretty simple. It's got a div, an ID of root, and there's a script tag that then brings in the source for application, which mounts itself onto that root component, and there you go. But if you don't have JavaScript running, well, nothing's gonna happen. It's just gonna be the white page. Whereas in the next application, you can see the HTML right at the start of it.

    And that's because what's happening is when you make a request to the Next.js server, it's first running our application on the server, generating that HTML, and then it sends that to the client as well as a script tag for a bundle, which then has our React code in it. That then runs again on the client and is hydrated, and then those two come up to sync, and then you've got a running application. But in the meantime, you've got something on the screen. It's not just good for the customer, it's also good for the Googlebot. Search engines look at the output of servers to go and see what the HTML is.

    Supposedly, they will run stuff on the client. Opinions vary on that, but SEO experts often agree that it's best to server-side render your applications so you're actually just sending the HTML to the Googlebot that you want it to see and not having it actually run the JavaScript code. Now there's one more thing I want to point out here. Let's jump back into our Next.js code. So I'm going to create a new component.

    I'm going to call it ClientComponent. We haven't really talked about ClientComponents yet, but ClientComponents are how you have components that are interactive on the client. So I'm just going to create a simple ClientComponent. It's going to say hello from the client and I will use the use client directive and I'll use the use client directive to make sure that this runs both on the client and the server. So let's go over to our page, I'll import that and then I'll use it in our code.

    Now let's go take a look. Now we can see that we have that on our client. If we take a look at the rendered HTML, we can see right there that we have Hello from Client in our output from our server. What that means is that Client components run on both the Client and on the server. I'm going to reemphasize this so many times in this course because that is the number one misconception that I see when it comes to Next.js.

    People believe that useClient means that those components will only ever run on the client. That's simply not the case. They run on both the client and the server. Now I'm going to take that code out and we'll go and continue on with adding authorization to our application. See you in the next video.