در پاسخ به این سوال که Next.js چیست باید بگوییم که یک فریمورک React برای توسعه قسمت فرانتاند وب است که عملکردهایی مانند رندر در سمت سرور و تولید سایت استاتیک را امکانپذیر میکند. در این مقاله قصد داریم تا مفاهیم مربوط به Next.js را باهم بررسی کنیم و بیشتر با این فریمورک آشنا شویم.
همینطور در ویدیو Next.js چیست – بررسی امکانات و کاربردها کانال یوتیوب فرانت کست هم به این موضوع پرداختهایم که مشاهده آن را پیشنهاد میکنیم.
در یک برنامه متداول React، کل برنامه لود شده و به کلاینت ارائه میشود. Next.js اجازه میدهد تا لود شدن صفحه اول توسط سرور انجام شود که این کار برای مبحث SEO و افزایش عملکرد بسیار موثر است.
برای نصب و ساخت پروژه Next.js میتوانیم از دستور npx به شکل زیر استفاده کنیم:
npx create-next-app my-app-name
و یا این که میتوانیم پیش پیکربندی Tailwind CSS را به صورت زیر بهکار بگیریم:
npx create-next-app -e with-tailwindcss my-app-name
با انجام این کار یک پوشه میسازیم که همه فایلها، تنظیمات و هر چیزی که برای راهاندازی برنامه Next.js نیاز داریم داخل آن ایجاد میشود.
پس از ساخت برنامه اکنون میتوانیم آن را راهاندازی کنیم:
cd your-app-name npm run dev
دستور بالا برنامه خالی Next.js ما را راهاندازی میکند که بهطور پیشفرض یک صفحه خوش آمدگویی از قبل برای ما ایجاد شده است.
برای مدیریت مسیرها در Next.js مجبور نیستیم از کتابخانه مسیریابی استفاده کنیم. بلکه پیادهسازی مسیریابی Next.js بسیار آسان است.
هنگامی که یک برنامه Next.js جدید با دستور create-next-appمیسازیم برنامه بهطور پیشفرض یک پوشه به نام pagesایجاد میکند.
این پوشه pages مسئولیت مدیریت مسیرهای ما را برعهده دارد. بنابراین هر فایل کامپوننت React در پوشه به عنوان یک مسیر خاص در نظر گرفته میشود.
به عنوان مثال اگر پوشه حاوی فایلهای زیر باشد:
index.jsabout.jsblog.jsاین فایل به طور خودکار به 3 مسیر تبدیل میشود:
localhost/indexlocalhost/aboutlocalhost/blogهمانطور که میبینید قاعده کلی این مفهوم بسیار آسان است.
همچنین، اگر از مسیری بازدید کنیم که وجود نداشته باشد مانند localhost/home، در این صورت Next.js به طور خودکار صفحه not found 404 را نشان خواهد داد.
در ادامه نمونهای از صفحه about.jsرا داریم. همانطور که مشاهده میکنید توضیح زیادی در مورد این صفحه مشخص نشده است، بلکه فقط یک کامپوننت functional معمولی React است.
function AboutPage() {
return (
<div>
<h1>About</h1>
</div>
)
}
export default AboutPage
برای ایجاد مسیرهای تودرتو همانند localhost/blog/contact، باید یک پوشه فرعی بسازیم. به عنوان مثال: pages/blog
در داخل آن پوشه میتوانیم کامپوننت contact.jsرا ایجاد کرده و صفحه localhost/blog/contactرا بسازیم.
اگر یک فایل index.jsدر آن زیر پوشه ایجاد کنیم، Next.js از آن کامپوننت برای نشان دادن مسیر root ما استفاده میکند. مثلا: localhost/blogمسیر pages/blog/index.jsرا رندر میکند.
اما اگر یک فایل در pages/blog.jsو فایل دیگری در pages/blog/index.jsایجاد کنیم، هر دو نشان دهنده یک مسیر یکسان localhost/blogهستند. در این صورت Next.js فقط فایل blog.jsرا رندر خواهد کرد.
اما درمورد مسیرهای پویا راهحل دیگری وجود دارد. به عنوان مثال مسیر هر پست وبلاگ که یک مسیر منحصربفرد است میتواند شبیه مثال زیر باشد:
localhost/blog/my-first-bloglocalhost/blog/my-second-blog-postدر Next.js میتوانیم با استفاده از علامت []یک مسیر پویا ایجاد کنیم. مثلا: pages/blog/[slug].js
متغیر Slug را میتوانیم با استفاده از هوک useRoute از route استخراج کرده و در مسیر پویایی که داریم مورد استفاده قرار میدهیم.
در ادامه نمونهای از صفحه [slug].jsرا بررسی میکنیم:
import { useRouter } from 'next/router'
function PostPage() {
const router = useRouter()
return (
<div>
<h1>My post: {router.query.slug}</h1>
</div>
)
}
export default PostPage
این یک مثال بیسیک است. در یک برنامه واقعی، از متغیر Slug برای لود کردن فایل پست یا جستجو در پایگاه داده برای پست مربوط به آن استفاده میشود.
اکنون اولین مسیر خود را ایجاد کردیم، سوالی که ممکن است پیش بیاید این است که چگونه میتوانیم صفحات را از طریق لینک به مسیرها ارتباط دهیم؟ برای انجام این کار به next/linkنیاز داریم. در مثال پایین میخواهیم از صفحه اصلی به صفحه about لینک ایجاد کنیم:
import Link from 'next/link'
export default function Home() {
return (
<div>
<h1>Home</h1>
<Link href="about">About</Link>
</div>
)
}
اگر میخواهیم در صفحه about لینکی ایجاد کنیم تا به صفحه اصلی بازگردیم میتوانیم به شکل زیر عمل کنیم:
<Link href="/">Home</Link>
همینطور اگر بخواهیم لینکی که داریم استایل مخصوص خود را داشته باشد باید از سینتکس زیر استفاده کنیم:
<Link href='/about'>
<a className="text-blue-500">About this project</a>
</Link>
اگر بخواهیم به شکل اجباری به یک صفحه خاص تغییر مسیر دهیم، به عنوان مثال هنگام کلیک روی یک دکمه به یک صفحه خاص هدایت شویم برای این کار میتوانیم از router.pushاستفاده کنیم:
import Link from 'next/link'
import { useRouter } from 'next/router'
function About() {
const router = useRouter()
return (
<div>
<h1>About Page</h1>
<p>This is the about page</p>
<button onClick={() => router.push('/')}>Return to home</button>
</div>
)
}
اغلب همه ما میخواهیم تا یک کامپوننت و یا یک فایل layout ایجاد کنیم. به عنوان مثال یک کامپوننت برای رندر کردن navbar.
تا به حال فقط از پوشه pagesاستفاده کردهایم اما اگر نخواهیم کامپوننتی که داریم یک صفحه با مسیر مجزا باشد، مثلا نمیخواهیم کاربر صفحهای مانند localhost/navbarرا باز کند در این صورت باید تمام کامپوننتهایی که میخواهیم صفحه مستقلی برای خود نداشته باشند را در یک پوشه دیگر قرار دهیم.
طبق قرارداد موجود، Next.js اکثرا از پوشهای با نام componentsاستفاده میکند و این پوشه در پوشه اصلی برنامههای ما ایجاد میشود. بنابراین برای مثال اگر میخواهیم یک کامپوننت layout بسازیم، میتوانیم آن را در یک پوشه کامپوننت جدید ایجاد کنیم: /components/Layout.js
از آن کامپوننت React میتوانیم در هر قسمت از برنامه خود استفاده کنیم، اما به عنوان یک صفحه دارای مسیر مرجع نخواهد بود.
Next.js سمت سرور برای لود شدن صفحه اول را رندر میکند. برای انجام این کار، باید تغییراتی را html صفحه خود را اعمال کنیم از جمله قسمت هدر.
برای اینکه تگهای بخش هدر مانند title یا meta را تکمیل کنیم باید از کامپوننت هد Next.js استفاده کنیم. در مثال زیر با استفاده از کامپوننت Head یک کامپوننت Layout ایجاد کردهایم:
// components/Layout.js
import Head from 'next/head'
function Layout({title, keywords, description, children}) {
return (
<div>
<Head>
<title>{title}</title>
<meta name='description' content={description}/>
<meta name='keywords' content={keywords}/>
</Head>
{children}
</div>
)
}
export default Layout
Layout.defaultProps = {
title: 'This is my app title',
description: 'This is my app description',
keywords: 'web, javascript, react, next'
}
در Next.js امکان ایجاد یک صفحه سفارشی 404 not found وجود دارد. زیرا ممکن است بخواهیم پیامی که میخواهیم به کاربر نمایش دهیم را شخصیسازی کنیم و یا layout صفحه خود را اضافه کنیم.
برای این کار باید فایل 404.jsرا در پوشه pagesایجاد کنیم. در این صورت هنگام مواجهه با خطای 404، Next.js به طور خودکار به این صفحه هدایت میشود.
در ادامه نمونهای از توسعه صفحه 404 را مطرح کردهایم:
// pages/404.js
import Layout from '../components/Layout'
function NotFoundPage() {
return (
<Layout>
Sorry the page you are looking is no where to be found.
</Layout>
)
}
export default NotFoundPage
همانطور که برنامه ما در حال رشد است میتوانیم برخی از کامپوننتها را به شکل تودرتو در ساختار پوشه برنامه قرار دهیم.
import Layout from '../../components/Layout'
بنابراین میتوانیم shortcutای ایجاد کنیم تا آدرسدهی را کوتاهتر کند و همان نتیجهی قبلی را به ما بدهد:
import Layout from '@/components/Layout'
کاراکتر @ یک دستور shortcut است.
برای ایجاد این shortcut و موارد دیگر، باید یک فایل با نام jsconfig.jsonدر root برنامه خود ایجاد کنیم:
// jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["components/*"],
}
}
}
به جای fetch کردن دادهها در سمت کلاینت، Next.js میتواند رندر سمت سرور را در یک صفحه فعال کند و امکان جمعبندی دادههای اولیه را به ما بدهد، این به معنای فرستادن صفحه با دادههایی است که قبلاً از طریق سرور ارسال شده است.
برای پیادهسازی fetch کردن دادههای سمت سرور، 2 راه داریم:
برای رندر شدن سمت سرور در هر درخواست، باید از تابع getServerSidePropsاستفاده کنیم. میتوانیم این تابع را در انتهای فایل کامپوننت خود اضافه کنیم:
export async function getServerSideProps() {
const res = await fetch(`http://server-name/api/items`)
const items = await res.json()
return {
props: {items},
}
}
اگر آن تابع در فایل کامپوننت ما وجود داشته باشد، Next.js به طور خودکار props کامپوننت را با آبجکت getServerSidePropsپر میکند.
برای رندر شدن سمت سرور در زمان ساخت باید از تابع getStaticPropsاستفاده کنیم. میتوانیم این تابع را در انتهای فایل کامپوننت خود اضافه کنیم:
export async function getStaticProps() {
const res = await fetch('http://server-name/api/items')
const items = await res.json()
return {
props: {items},
}
}
همچنین ممکن است بخواهیم دادهها را در زمان ساخت اما برای یک مسیر پویا fetch کنیم، مثلا /posts/my-first-post.
فرض کنید یک صفحه با نام posts/[slug].jsداریم که به ما مسیرهای posts/my-first-post، posts/my-second-blogو غیره را میدهد. در این شرایط میتوانیم از getStaticPathsبرای ایجاد تمام آن مسیرهای فرعی در زمان ساخت استفاده کنیم.
export async function getStaticPaths() {
const res = await fetch(`${API_URL}/posts`)
const posts = await res.json()
const paths = posts.map(post => ({params: {slug: post.slug}}))
return {
paths,
fallback: true,
}
}
export async function getStaticProps({params: {slug}}) {
const res = await fetch(`${API_URL}/posts?slug=${slug}`)
const posts = await res.json()
return {
props: {
post: posts[0]
}
}
}
Next.js دارای یک کامپوننت داخلی و بهینهسازی خودکار تصویر است اما منظور از این کامپوننت چیست؟ کامپوننت تصویر Next.js که next/imageاست، یک فرمت از المنت HTML میباشد و برای وب مدرن طراحی شده است.
تصاویر بهطور پیشفرض دارای Lazy loading هستند، یعنی این که آنها هنگام نیاز و با اسکرول شدن در صفحه نمایش لود میشوند.
برای این کار ابتدا کامپوننت Imageرا import میکنیم:
import Image from 'next/image'
سپس به صورت زیر از آن استفاده میکنیم:
<Image
src="/image.png"
alt="Picture of the author"
width={500}
height={500}
/>
برای اینکه اطلاعات بیشتری درمورد کامپوننت Image در Next.js بدست بیاورید مطالعه این لینک میتواند مفید باشد.
دیدگاهها: