ArkarDev

Var.Camp 2023

Feb 8, 2023Arkar Kaung Myat
NextjsReactVar.Camp

A brief catch up on what discussed at var.camp.

I participated in an amazing event called var.camp  which is an online virtual barcamp for everyone around the world. I discussed the topic of next.js and react. This article gonna be brief catch-up on what we discussed at the event.

# Next.js 13

For those of you who don’t know what Next.js is, Next.js is a meta-framework built on top of React for building websites which allow the developer to develop faster and more performant websites. It provides easy APIs for

  • User interfaces - how users will consume and interact with your application.
  • In Routing - how users navigate different parts of the application
  • Data fetching - where your data lives and how you get it
  • Rendering - when and where you render static or dynamic content.
  • Developer Experience - your team’s experience building and maintaining your application.
  • API routes - create your API endpoints

# Rendering Strategies in Next.js

When using React for building websites, there is an unavoidable unit of the process to convert the code you write in React to HTML for the presentation of UI. Rendering can take up everywhere either in the server or in the client.

With Next.js, three types of rendering methods are available:

  • Server-side Rendering
  • Static Site Generation and
  • Client-side rendering

Serverside rendering and static site generation are called pre-rendering because the process of fetching data from external APIs and the transformation of React into HTML is done before the result is sent to the client.

In a standard React application ( e.g create-react-app ), the browser receives a bundle of Javascript with a set of instructions to construct the UI in the client’s browser. This is called client-side rendering because the transformation or initial rendering process happens in the client’s device.

That means for a full client-side rendering app, the user will see a blank page while the rendering process is being done on the device.

Next, every page is pre-rendered by default in the browser. HTML is generated in advance, instead of having it done by Javascript in the client device.

With server-side rendering, the HTML of the page is generated on a server for each request. The generated HTML, JSON data, and JavaScript instructions to make the page interactive are then sent to the client.

On the client, the HTML is used to show a fast non-interactive page, while React uses the JSON data and JavaScript instructions to make components interactive which is also known as hydration.

With Static Site Generation, the HTML is generated on the server, but unlike server-side rendering, there is no server at runtime. Instead, content is generated once, at build time, when the application is deployed, and the HTML is stored in a CDN  and re-used for each request.

Next.js allows you to create or update static pages after you’ve built your site. Incremental Static Regenerat

ion (ISR) enables you to use static generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.

function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time on the server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 10 seconds
    revalidate: 10, // In seconds
  }
}

// This function gets called at build time on the server-side.
// It may be called again, on a serverless function, if
// the path has not been generated.
export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: blocking } will server-render pages
  // on-demand if the path doesn't exist.
  return { paths, fallback: 'blocking' }
}

export default Blog

# Server components

In the discussion, we also discussed Server components which play a huge part in Next.js version 13. I share an amazing analogy from Dan  when meta announce react 18 in 2020.

In building React applications, we always come up with a situation like this. We have a blog-detail component's children, which require different data related to blogId to get data for the component.

function BlogPage({ blogId }) {
  return (
    <BlogDetails>
      <RelatedBlog />
      <RecommandedBlog />
    </BlogDetails>
  );
};

// get data from server
function BlogPage({ blogId }) {
  const data = getData();
  return (
    <BlogDetails blogId={blogId} data={data.details}>
      <RelatedBlog blogId={blogId} data={data.related} />
      <RecommandedBlog blogId={blogId} data={data.recommended} />
    </BlogDetails>
  );
}

This is not the end of the world but what happened is our data is completely bound to the UI which costs higher effort to maintain the code base. If we don’t need recommended data in some aspects we might end up over-fetching the data or if we have to add some data fields we might need to make sure our component always syncs with the data schema. But an amazing community of react come up with tips and tricks to overcome cases like this.
How about we separate the logic into its required components?

function BlogDetails({ blogId, children}){
  const details = getBlogDetails(blogId)
  return(
    ...
  )
}

function RelatedBlogs({ blogId }){
  const related = getRelatedBlogs(blogId)
  return(
    ...
  )
}

function RecommededBlogs({ blogId }){
  const details = getRecommendedBlogs(blogId)
  return(
    ...
  )
}

The code here is completely fine and we used that a ton of times. The problem here is the performance issue. In this case, both the related blogs and recommended blogs will not execute until the blog details data has arrived and that’s how Javascript works. We might end up with a situation called the waterfall problem where we will have to wait for chains of functions to get called one by one.
Another issue is that most of the React code gets executed on the client which can have various environmental factors on how the user gets the UI.


The idea is to move all the react components to get executed on the server so that users can receive zero bundle UI implementations without needing to add to the JavaScript bundle.


React Server Components allow the server and the client to work together to render your app.


For example, the following React element tree is composed of React components that render other React components. React Server Components allow some components to render on the server, some to render in the browser or on the server using server-side rendering (SSR), and others to render on both the server and the client.

[RFC]: If we migrate the above example to a Server Component we can use the exact same code for our feature but avoid sending it to the client - a code savings of over 240K (uncompressed):

I also did a demo to showcase the API provided by next and how we can use server components in the latest next.js 13.

Slides

Demo

Github : https://github.com/Riley1101/varcamp-next13-demo