We started developing React React-based front-ui. It was all good during development. Beta Testing exposed a common problem: initial pages were taking a considerable amount of time to load. The front microservice pattern was followed (using module federation), and it helped us a lot. However initial page loading was frustrating for some of our clients, specifically those located in regions where internet speed is a constraint. Finally, we were able to reduce speed and improve user experience using NextJS.
What is NextJS?
NextJS is an extension of ReactJS that provides features like Server Side components, Client and Server Rendering, Data fetching with revalidation, and built-in optimizations. This makes NextJS extremely powerful for creating fast WebApps that take no time to load web pages.
What are server-side components in NextJS?
Now NextJS gives us freedom to decide if we want a component to be rendered at client or server. In a given page we can find some sections that are non-interactive and whose data remains rather static. Such components should be created as Server side components (server-first approach). This is because Server Components allow us to implement data-fetching logic on the server. This reduces client JavaScript bundle size leading to improved performance.
What are Client Side Components in NextJS?
Client-side components should be used where interactivity is required or where we are supposed to use hooks such as for state management. Client-side components are pre-rendered at the server but hydrated at the client. Hydration is injecting JavaScript into HTML Skeleton so as to make it interactable.
In the diagram below Product detail remains rather static, and so it should be a Server-side component. However “AddToCart” feature has to be interactive, it should be a Client-side component.
Server Components and Client Components in NextJS
How Routing is implemented in NextJS?
NextJS V13 supports “App Router” with support for Server Side Components. It supports shared layouts, nested routing, loading states, and error handling. This is better than “Page routing” supported by earlier versions. Read this section to learn more about routing.
Dynamic routing in NextJS
Dynamic routing allows us to create routes from dynamic data. For example /app/repo/google and /app/repo/Twitter and app/repo/amazon have a common prefix segment /app/repo but different repo names (google, Twitter, amazon). This repo name represents a dynamic segment.
We can create dynamic segments in NextJS by creating folders containing dynamic segment name inside [].
So we have to create a folder named “app/repo/[slug]” and three files inside this folder with predefined names as follows:
Component: app/repo/[slug]/page.tsx
For Loading State: app/repo/[slug]/loading.tsx
For Error handling: app/repo/[slug]/error.tsx
Note that [slug] represents a dynamic segment.
Directory structure for dynamic segments
Server-side data fetching
fetch() method is used to fetch remote data. Caching is enabled by default, so subsequent invocations to fetch() for the same URL will return cached data.
Thusfetch(<url>)
is same as fetch(<url>,{ cache: ‘force-cache’ })
Selecting routes to be generated at build time
Just define generateStaticParams() inside page.tsx.
The implementation of this method should return an array containing dynamic segment value for which quote will be generated export async function generateStaticParams() { return [“Twitter”,”Microsoft”,”google”, “amazon”]; }
If we want to prevent the on-demand generation of routes other than specified by generateStaticParams() we can set it as follows://this is true by default export const dynamicParams = false;
This means any dynamic segment other than that returned by generateStaticParams() will throw a 404
Sample Application
The following api returns github user info for the given <user_name>https://api.github.com/users/<user_name>
Our App will fetch and display user info for twitter, microsoft, google and Amazon. Any attempt to view any other user-info is restricted (dynamicParams = false)
Sample App explaining Server Side components in NextJS
As we can see visiting Twitter for the first time is taking a considerable amount of time. However once the result is cached, subsequent visits are blazingly fast. We have intentionally introduced a delay of two seconds inside getData() to explain it better. (Never do this in production).
Note that it is a Server Side component (It’s default, to create Client Side Component we have to write ‘use client’ as the first statement) and we are not using conventional mechanisms like useEffect() to fetch data. Remember that using hooks such as useState(), and useEffect() are prohibited for server-side components, for hooks are meant to make client-side functional.
Data Revalidation
Revalidation is the process of fetching the latest data and overwriting what already exists in the cache. For example, we want the news bulletin to be updated every hour (Time-based revalidation), we can set the revalidation policy as follows://Revalidate cache Every I hour (3600 seconds) fetch(“https://myapi.com/news/articles/” + slug,{ next: { revalidate: 3600 }});
On Demand revalidation:
revalidateTag(<tagName>) and revalidatePath(<path>) may be used for on-demand validation. You can read more about on-demand validation here .
Conclusion: If you want super-fast user facing UIs with server side rendering or SSG, Image optimization and other demands as raised by modern front end world, NextJS is one of the best choice.
We started developing React React-based front-ui. It was all good during development. Beta Testing exposed a common problem: initial pages were taking a considerable amount of time to load. The front microservice pattern was followed (using module federation), and it helped us a lot. However initial page loading was frustrating for some of our clients, specifically those located in regions where internet speed is a constraint. Finally, we were able to reduce speed and improve user experience using NextJS.
What is NextJS?
NextJS is an extension of ReactJS that provides features like Server Side components, Client and Server Rendering, Data fetching with revalidation, and built-in optimizations. This makes NextJS extremely powerful for creating fast WebApps that take no time to load web pages.
What are server-side components in NextJS?
Now NextJS gives us freedom to decide if we want a component to be rendered at client or server. In a given page we can find some sections that are non-interactive and whose data remains rather static. Such components should be created as Server side components (server-first approach). This is because Server Components allow us to implement data-fetching logic on the server. This reduces client JavaScript bundle size leading to improved performance.
What are Client Side Components in NextJS?
Client-side components should be used where interactivity is required or where we are supposed to use hooks such as for state management. Client-side components are pre-rendered at the server but hydrated at the client. Hydration is injecting JavaScript into HTML Skeleton so as to make it interactable.
In the diagram below Product detail remains rather static, and so it should be a Server-side component. However “AddToCart” feature has to be interactive, it should be a Client-side component.
How Routing is implemented in NextJS?
NextJS V13 supports “App Router” with support for Server Side Components. It supports shared layouts, nested routing, loading states, and error handling. This is better than “Page routing” supported by earlier versions. Read this section to learn more about routing.
Dynamic routing in NextJS
Dynamic routing allows us to create routes from dynamic data. For example /app/repo/google and /app/repo/Twitter and app/repo/amazon have a common prefix segment /app/repo but different repo names (google, Twitter, amazon). This repo name represents a dynamic segment.
We can create dynamic segments in NextJS by creating folders containing dynamic segment name inside [].
So we have to create a folder named “app/repo/[slug]” and three files inside this folder with predefined names as follows:
Note that [slug] represents a dynamic segment.
Server-side data fetching
fetch() method is used to fetch remote data. Caching is enabled by default, so subsequent invocations to fetch() for the same URL will return cached data.
Thusfetch(<url>)
is same as fetch(<url>,{ cache: ‘force-cache’ })
Selecting routes to be generated at build time
Just define generateStaticParams() inside page.tsx.
The implementation of this method should return an array containing dynamic segment value for which quote will be generated export async function generateStaticParams() {
return [“Twitter”,”Microsoft”,”google”, “amazon”];
}
If we want to prevent the on-demand generation of routes other than specified by generateStaticParams() we can set it as follows://this is true by default
export const dynamicParams = false;
This means any dynamic segment other than that returned by generateStaticParams() will throw a 404
Sample Application
The following api returns github user info for the given <user_name>https://api.github.com/users/<user_name>
Our App will fetch and display user info for twitter, microsoft, google and Amazon. Any attempt to view any other user-info is restricted (dynamicParams = false)
As we can see visiting Twitter for the first time is taking a considerable amount of time. However once the result is cached, subsequent visits are blazingly fast. We have intentionally introduced a delay of two seconds inside getData() to explain it better. (Never do this in production).
Note that it is a Server Side component (It’s default, to create Client Side Component we have to write ‘use client’ as the first statement) and we are not using conventional mechanisms like useEffect() to fetch data.
Remember that using hooks such as useState(), and useEffect() are prohibited for server-side components, for hooks are meant to make client-side functional.
Data Revalidation
Revalidation is the process of fetching the latest data and overwriting what already exists in the cache. For example, we want the news bulletin to be updated every hour (Time-based revalidation), we can set the revalidation policy as follows://Revalidate cache Every I hour (3600 seconds)
fetch(“https://myapi.com/news/articles/” + slug,{ next: { revalidate: 3600 }});
On Demand revalidation:
revalidateTag(<tagName>) and revalidatePath(<path>) may be used for on-demand validation. You can read more about on-demand validation here .
Conclusion:
If you want super-fast user facing UIs with server side rendering or SSG, Image optimization and other demands as raised by modern front end world, NextJS is one of the best choice.
Written by Muhammad Talha Waseem
Recent Posts
Recent Posts
🚀 Successfully Integrated Stripe with Java for
Free Tools Every ML Beginner Should Use
Spring Modulith vs Microservices: Understanding the Differences
Archives