Next.js 13 8 things you need to know

In this article, we'll take a deep dive into Next.js 13 and explore a few things you should know before using it for your next web app. Buckle up because we're about to embark on an exciting journey into the future of web development.

React Server Component (RSC)

The new Next.js 13 App Router is built in close collaboration with React 18. One of the major new features in React 18 is React Server Components (RSC). In order to start developing with Next.js 13, you need to think around this new paradigm.

In the past, React was primarily a client-side UI rendering library. By adding RSC, the aim is to render as much of your application as possible on the server at build time (we'll detail the different rendering modes below).

When a route is loaded with Next.js, the initial HTML is rendered on the server. This HTML is then progressively enhanced in the browser, allowing the client to take over the application and add interactivity, by asynchronously loading the Next.js and React client-side runtime.

From Next.js official documentation: React Essentials section

When loading a route using Next.js, the initial HTML is rendered on the server. This HTML is then progressively enhanced in the browser, allowing the client to take over the application and add interactivity by asynchronously loading Next.js and the React client runtime.

In React 18, two new directives use clientand are added use serverto control where components are rendered at the file level. These new directives are used in Next.js 13 to control whether code is included in the client bundle.

Using use serverthe directive, we can indicate that the component does not need to be included in the bundle loaded by the client. Components will be rendered on the server at build or run time.

As you can see in the code below, we can also async awaituse in server components, which makes them perfect for loading data.

// ServerComponent.ts
"use server"

export default async function ServerComponent() {
    
    
  const data = await fetchData()

  return //...
}

For more information, see the original React RFC, where these directives were proposed: https://github.com/reactjs/rfcs/pull/227

The server component is enabled by default in Next.js

In the Next.js 13 world, server components are now the default components, which means most components don't need the use clientor use serverdirective.

These instructions are only needed when creating boundary components.

// page.tsx
// React Server Component, will not be included in the client 
export default function Page() {
    
    

  return (
    <Provider>
      <TodoList />
    </Provider>
  )
}

// TodoList.tsx
// use client is needed here since we are using React hooks
"use client"
export default function TodoList() {
    
    
  useEffect(() => {
    
    })

  return (
    <>
      {
    
    todos.map(todo => <Todo {
    
    ...todo} />)}
    </>
  )
}

// TodoList.tsx
// No "use client" needed here, even though we are using hooks
// because this component is only ever rendered within another client component
export default function Todo() {
    
    
  useEffect(() => {
    
    })

  return (
    <>
      {
    
    todos.map(todo => <Todo {
    
    ...todo} />)}
    </>
  )
}

Client components are rendered on the server too!

When you use clientdevelop a client-side component using the directive, it does not mean that it is only rendered on the client side. In fact, most client-side components are rendered on the server when performing server-side rendering (SSR) or static site generation (SSG).

Client components will only be rendered if you explicitly instruct them not to be rendered on the server. One way is to use the with next/dynamicoption ssr: false(note: Vercel recommends using directly React.lazyand Suspenseinstead next/dynamic):

import dynamic from 'next/dynamic';
 
const DynamicHeader = dynamic(() => import('../components/header'), {
    
    
  ssr: false,
});

This makes Next.js a true hybrid framework and drives Next's goal of statically rendering as much content as possible and only including what the client needs.

This means you need to think about how your client components will be rendered on the server. One way to test this is to disable JavaScript in your browser and see how the page renders. What you should see is the page fully rendered, but with interactive elements disabled.

You need to ensure that you don't introduce layout shifts when elements become interactive, so make sure your components render well before enabling JavaScript, either by defaulting to rendering content or using a skeleton.

Compilation of client and server components

Next.js 13 provides enhanced flexibility when packaging components. Server components can render other server components and client components. Client components, on the other hand, can render other client components, and propserver components can only be rendered if they are passed in as . This layered composition model allows for a high degree of interoperability and code reusability.

I know the above paragraph is a bit insensitive. Here is a great diagram created by the folks at Vercel to help you better visualize this concept:

Here is a quick example h

Next.js 13 rendering modes

Next.js 13 introduces different rendering environments and modes, allowing you to choose the best rendering strategy for your app on a component-by-component basis.

Content is presented in two different environments:

  • Client side — Client-side components are pre-rendered and cached on the server. JSON is generated for the data used on the client component and passed to React during hydration.
  • Server side — Content is rendered on the server by React and static HTML is generated. React uses static HTML to hydrate the browser and requires no additional JavaScript on the client.

On the server, two different rendering modes are used:

  • Static — Both client and server components are rendered as static HTML when built. Static content can be revalidated , allowing page-by-page updates to keep dynamic data in sync with its source. Static generated content is easily cacheable, improving performance, user experience, and SEO.
  • Dynamic — Both client and server components are rendered on the server when a request is made. Content is not cached.

Earlier versions of Next.js had different terminology for these concepts. I'll include them below and show how they relate to the new Next.js 13 terminology.

  • Static-site generation (SSG): Static site generation (SSG) static rendering mode
  • Incremental Static Regeneration (ISR): Static rendering mode with revalidation
  • Server-side Rendering (SSR): Server-side rendering (SSR): dynamic rendering mode
  • Client-side Rendering (CSR): Client-side rendering (CSR): Client-side components

Be sure to check out the Next.js documentation on this topic .

The bucket file is a bit corrupted

In the past, it was a common practice to add index files (sometimes called bucket files) to modules to allow for better imports and more control over what was exported from the module. For example, you might have a utils/directory with several files containing utilities:

.
└── utils/
    ├── api.ts
    ├── dom.ts
    ├── formatter.ts
    ├── parser.ts
    └── index.ts

In this case, index.tsthe file might look like this:

export {
    
     default as parser } from './parser'
export {
    
     default as formatter } from './formatter'
export * from './api'

This allows you to import one of your utilities, for example:

import {
    
     parser } from 'utils'
// 而不是:
import parser from 'utils/parser'

This pattern becomes a bit trickier in Next.js 13, as it has the ability to accidentally leak server-only code into the client. Next.js has a useful utility that allows you to import "server-only"add a : to the top of a module so you can prevent it from being loaded in the client bundle. It is recommended that you use this for the bucket file and import the client utility from its direct path. You can also add separate "client-only" bucket files to ensure that modules for client and server are not mixed.

Library Integration: WIP is still a work in progress

The open source community has come a long way, but there are still some libraries that don't integrate as well as we would like. For example, MUI, Emotion, Styled Components, and Apollo GraphQL all have minor issues or irregularities on Next.js 13 App Router.

For example, with Material UI (MUI), you may find yourself stuck and have to resort to some "unorthodox" logic, or as an alternative, designate most components as client-side components. For more insights on this specific issue, I highly recommend visiting the following GitHub discussions: Issue #34896 and Issue #34905 .

If you are using Apollo, you may encounter situations where you need to get the same data on both the client and the server. The solution to this problem lies in hydrating Apollo's cache, but it does require some elbow grease. Thankfully, Apollo has released an experimental package to assist with this: you can learn more and read their official announcement here .

Route groups routing groups

Route groups are a nifty feature introduced in Next.js 13, especially if your app requires multiple root layouts. Next.js 13.3 removes deprecated head.jsspecial files and replaces them with generateMetadataAPIs. One disadvantage of this approach is that <head>it is difficult to add scripts when your pages have different content.

For example, assume that part of your application has navigation loaded from an API. The API returns headthe contents of its script dependencies. Routing groups solve this problem by allowing you to split parts of your application into different folders with their own root layout.

.
├── (navigation)/
│   ├── dashboard/
│   │   └── page.tsx
│   └── layout.tsx
└── (navless)/
    ├── auth/
    │   └── page.tsx
    └── layout.tsx

In the example above, the dashboard page has its own root layout that can contain additional header content loaded from the API:

import {
    
     PropsWithChildren } from 'react'

export default async function Layout({
    
     children }: PropsWithChildren) {
    
    
  const {
    
     head, header, footer } = await fetchNavigationMarkup()

  return (
    <html>
      <head>
        {
    
    head}
      </head>
      <body>
        {
    
    header}
        {
    
    children}
        {
    
    footer}
      </body>
    </html>
  )
}

Summarize

In this article, we take a deep dive into 8 things you need to know before getting started with Next.js 13.

From the default server components, to the nuances of component composition, library integration quirks, different rendering modes, and the introduction of routing groups—there's a lot to understand before getting started.

While it wasn't without its growing pains, Next.js 13 is a leap forward for the framework, pushing what's possible in web development.

As you enter the realm of Next.js 13, remember that with great power comes great responsibility. Use these features wisely and you'll be building some truly stunning web applications in no time. Stay curious, keep exploring, and never stop learning. Until next time, happy coding!

Guess you like

Origin blog.csdn.net/jslygwx/article/details/132389913