In the last tutorial, we used Next.js as frontend for our Laravel based app. Let’s delve into Next.js for a while to see what this JS framework has to offer and why everyone’s clamoring around it.
Next.js started itself as an extension of React which primarily dominates at the client-side. However, as of late React has been transforming into full-stack framework and with the introduction of App Router, Next.js 13 is claiming itself to be backend first framework. Let’s have a quick introduction of key concepts of Next.js 13 framework.
Routing
Routing in Next.js is file-system based which is built on top of React Server Components (RSCs), that supports layouts, nested routing, loading states, error handling, and more. App Router is represented by app folder within Next.js app’s folder structure. And then each folder inside app folder represents a route. For example, the following folder structure has a routing system with three routes:
/app
layout.js
page.js
/dashboard
page.js
/settings
page.js
The /app folder defines the root / route, similarly the /app/dashboard folder defines the /dashboard route, and the /app/dashboard/settings folder defines the /dashboard/settings route.
A special page.js file (extension of file will be .tsx in case of Typescript) is used to make route segments publicly accessible. In other words, the page.js files within /app , /app/dashboard and /app/dashboard/settings contain the contents which are publicly accessible and the respective page.js file gets rendered when the related route is accessed. A simple page.js would be as follows:
export default function Page() {
return <h1>Hello World!</h1>
}
There is also a special file layout.js which defines the layout for the given route and all its children routes. We have to have a parent layout.js (Root Layout) in the /app folder which actually contains the <html> and <body> parts of the app:
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Linking
To navigate to a different route, you can use the Link component. The Link component in Next.js is a React component that extends the HTML <a> element.
The Link component takes a href prop, which contains the URL of the route you want to navigate to. For example, the following Link will navigate to the /dashboard route:
...
import Link from 'next/link'
...
<Link href="/dashboard">Your workspace</Link>
We can also utilize useRouter() hook to change the routes programmatically. However, this hook, along with other hooks like useState(), useEffect() etc., can only be used inside client-side components.
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
Data rendering and fetching
As of late, the action is moving back to server-side; the latest iteration of Next.js embraces the offerings of RSCs. Now, each component within app folder is rendered server-side by default. And, in order to make a component client-side, we explicitly have to mention ‘use client’ at the beginning of that component.
We use fetch() for data fetching inside Next.js which extends the native Fetch Web API to incorporate the caching and revalidation functionality. In Next.js app development, it’s recommended to use server-side component for data fetching.
async function getData() {
const res = await fetch('https://api.example.com/...')
if (!res.ok) {
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
For data fetching inside client-side components, you can either use Fetch Web API (without async / wait), Route Handlers or third party library such as SWR.
'use client'
import useSWR from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json());
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (isLoading) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
Optimizing
Next.js offers some of the crucial optimizations out-of-the-box using special components such as Image, Metadata, Script.
The Image component in Next.js is a powerful tool for handling images which makes it easy to optimize the images for performance and SEO.
With Metadata component, you can modify the <head> HTML elements such as title and meta for SEO support. Metadata can be defined by exporting a metadata object in a layout.js or page.js file:
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
By using Script component in layout, Next.js makes sure that the script will load only once, even if a user navigates between multiple routes within the same layout.
Here, we’ve covered some of the core concepts in Next.js. In next article, we’ll create a simple Next.js 13 app to see these concepts in action.
1 thought on “Next.js 13 – Quick Intro”