در حال امتحان کردن فهرست برنامه در Next.js

راهنمای مبتدی برای کاوش دایرکتوری جدید برنامه Next.js و اجزای سرور
من از امتحان کردن پوشه برنامه جدید اجتناب کردهام، بیشتر به این دلیل که اخیراً عملکردهای سمت سرور Next.js را به دست آوردهام و از اینکه آنها چیز جدیدی را معرفی میکنند کمی ناراحت بودم. با این حال، در این زمینه، سازگاری و باز بودن برای یادگیری چیزهای جدید، به ویژه در اکوسیستم جاوا اسکریپت که به سرعت در حال حرکت است، مهم است.
برای کسانی از شما که آشنایی ندارید، Next.js یک فهرست برنامه جدید با طرحبندی و قراردادهای جدید معرفی کرده است. اگرچه آنها نگفته اند که جایگزین پوشه pages (روش قبلی ایجاد مسیرها) خواهد شد، به نظر می رسد که این کار جایگزین شود.
برای درک بهتر نحوه عملکرد طرحبندی جدید و اینکه ببینم آن را دوست دارم یا نه، تصمیم گرفتم یک برنامه ساده پوکمون ایجاد کنم.
بیا شروع کنیم
دستور زیر را برای ایجاد یک برنامه Next.js جدید اجرا کنید:
npx create-next-app@latest --typescript next-app-folder-pokemon
مطمئن شوید که به همه درخواستها «بله» پاسخ میدهید، مخصوصاً موردی که از شما می پرسد آیا می خواهید از دایرکتوری برنامه آزمایشی استفاده کنید.
اکنون به مسیر بروید next-app-folder-pokemon
فهرست راهنما
بیایید انواع TypeScript را برای Pokémon اضافه کنیم تا مطمئن شویم که TypeScript بعداً مشکلی ایجاد نمی کند.
src/types/index.ts
export interface Pokemon {
id: number;
name: string;
height: number;
weight: number;
abilities: {
ability: {
name: string;
};
}[];
sprites: {
front_default: string;
};
types: {
type: {
name: Types;
};
}[];
stats: {
base_stat: number;
stat: {
name: string;
};
}[];
}
interface PokemonFromList {
name: string;
url: string;
}
export interface Pokemons {
count: number;
next: string;
previous: string;
results: PokemonFromList[];
}
type Types =
| "normal"
| "fighting"
| "flying"
| "poison"
| "ground"
| "rock"
| "bug"
| "ghost"
| "steel"
| "fire"
| "water"
| "grass"
| "electric"
| "psychic"
| "ice"
| "dragon"
| "dark"
| "fairy";
علاوه بر این، باید نام میزبان تصویر (برای تصاویر پوکمون) را در قسمت مشخص کنیم next.config.js
فایل برای فعال کردن استفاده از مولفه Next’s Image برای نمایش تصاویر.
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
// here
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'raw.githubusercontent.com',
},
],
},
}
module.exports = nextConfig
در مرحله بعد، اجازه دهید یک پوشه خدمات در دایرکتوری src ایجاد کنیم. در اینجا، ما یک فایل pokemon.ts اضافه می کنیم که شامل دو تابع واکشی است که در این برنامه استفاده خواهیم کرد.
src/services/pokemon.ts
import { Pokemon, Pokemons } from "@/types";
const POKEMON_API = "https://pokeapi.co/api/v2";
export async function getPokemon(id: string): Promise<Pokemon> {
const response = await fetch(`${POKEMON_API}/pokemon/${id}`);
const data = await response.json();
return data;
}
export async function getPokemons(): Promise<Pokemons> {
// only fetch the first 151 pokemons
const response = await fetch(`${POKEMON_API}/pokemon?limit=151&offset=0`);
const data = await response.json();
return data;
}
اجزای سرور
دایرکتوری برنامه شامل ویژگی قابل توجهی از اجزای سرور است که به توسعه دهندگان این امکان را می دهد تا مؤلفه های React را بسازند که می توانند روی سرور کار کنند، شبیه به رندر سنتی سمت سرور. این ویژگی نه تنها عملکرد بهتری را ارائه می دهد، بلکه انعطاف پذیری بیشتری را نیز ارائه می دهد. اگرچه من فقط می توانم خلاصه ای کوتاه در اینجا ارائه کنم، اما می توانید با تماشای این گفتگوی آموزنده، این موضوع را بیشتر بررسی کنید.
چیزی که من به خصوص در مورد اجزای سرور قابل توجه یافتم این است که هنگام واکشی داده ها انعطاف پذیری بیشتری را ارائه می دهند. با اجزای سرور، توسعهدهندگان میتوانند منتظر عملکرد واکشی مستقیماً در کامپوننت باشند و نیاز به آن را از بین ببرند useEffect
قلاب برای واکشی داده ها این میتواند کد را سادهتر کند و مدیریت واکشی دادهها در اجزا را آسانتر کند.
بگذار بهت نشان بدهم.
را اصلاح کنید src/app/page.tsx
با مطالب زیر
import Image from "next/image";
import Link from "next/link";
import { getPokemons } from "@/services/pokemon";
const SPRITE_URL =
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon";
export default async function Page() {
// this magic here
const results = await getPokemons();
return (
<div>
<div>
{results.results?.map((pokemon, index) => (
<Link href={`/pokemon/${pokemon.name}`} key={pokemon.name}>
<Image
alt={pokemon.name}
width={100}
height={100}
src={`${SPRITE_URL}/${index + 1}.png`}
/>
<p>{pokemon.name}</p>
</Link>
))}
</div>
</div>
);
}
این صفحه لیستی از پوکمون ها را نمایش می دهد که می توان روی آنها کلیک کرد تا به صفحه مربوطه آنها بروید که به زودی آن را ایجاد خواهیم کرد.
در دایرکتوری برنامه جدید در Next.js، مسیرهای پویا به طور مشابه در پوشه صفحات قبلی کار می کنند. برای ایجاد یک مسیر پویا، باید یک پوشه با براکت مربع و نام پارامتری که می خواهیم استفاده کنیم ایجاد کنیم. به عنوان مثال، برای ایجاد یک مسیر پویا با استفاده از slug
پارامتر، ما یک پوشه به نام ایجاد می کنیم [slug]
در pages
فهرست راهنما. مهمترین فایل در این زمینه فایل است page.tsx
فایل، که هر چیزی را که از آن وارد شده است به عنوان یک صفحه تعریف می کند. در حالی که Next.js همچنین فایل های طرح بندی و قالب را برای سفارشی سازی پیشرفته تر ارائه می دهد، ما از آنها در این آموزش استفاده نخواهیم کرد.
برای ایجاد یک pokemon/:slug
مسیر، پوشه ها و فایل های زیر را در دایرکتوری برنامه ایجاد کنید pokemon/[slug]/page.tsx
، سپس محتوای زیر را داخل فایل اضافه کنید:
import Link from "next/link";
import Image from "next/image";
import { getPokemon, getPokemons } from "@/services/pokemon";
type Params = {
params: {
slug: string;
};
};
export default async function Pokemon({ params }: Params) {
const { slug } = params;
// magic strikes again
const pokemon = await getPokemon(slug);
const sprite = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/${pokemon.id}.svg`;
return (
<div>
<Link href="/">Home</Link>
<h1>{pokemon?.name}</h1>
<Image
width={400}
height={400}
src={sprite}
alt={pokemon?.name}
priority
/>
</div>
);
}
export async function generateStaticParams() {
const res = await getPokemons();
return res.results.map((pokemon) => ({
slug: pokemon.name,
}));
}
در این بلوک کد شاهد پیاده سازی صفحه پوکمون هستیم که به صفحه قبل لینک شده است. کامپوننت های لازم را از Next.js وارد می کند getPokemon
و getPokemons
توابع از pokemon
سرویس.
را Pokemon
تابع یک شی پارامتر با a را می گیرد slug
ویژگی، که برای واکشی داده های پوکمون خاص استفاده می شود. سپس از داده های واکشی شده برای نمایش نام و تصویر پوکمون در صفحه استفاده می شود. URL تصویر با استفاده از شناسه Pokemon و یک الگوی URL تصویر از پیش تعریف شده ساخته شده است.
یکی از تفاوتهای قابل توجه با نمونههای کد قبلی، اضافه کردن کد است generateStaticParams
تابع. این تابع جایگزینی برای getStaticPaths
تابع و مسئول تولید پارامترهای (در این مورد، راب) مورد نیاز برای تولید تمام صفحات پوکمون به صورت ایستا است.
به طور کلی، Pokemon
مؤلفه نسبتاً ساده است و از قدرت مؤلفه های سرور برای واکشی و نمایش داده های مورد نیاز برای هر صفحه پوکمون استفاده می کند.
فراداده
قبلاً اغلب از آن استفاده می کردم next-seo
کتابخانه ای برای رسیدگی به نیازهای فراداده من، اگرچه Next.js نیز a <Head/>
جزء برای این منظور. با این حال، پوشه برنامه جدید تغییراتی در نحوه مدیریت ابرداده دارد.
برای ابرداده استاتیک، می توانیم از metadata
هدف – شی.
بیایید نمونه ای از این را در فایل src/app/page.tsx ببینیم:
// at the end of the file
export const metadata = {
title: "Trying the new app folder",
description: "Pokemon app made with Next.js",
};
از آنجایی که هر صفحه پوکمون باید متادیتای منحصر به فردی با تصویر و اطلاعات خود داشته باشد، استفاده از ابرداده ثابت کافی نیست. src/app/pokemon/[slug]/page.tsx
. در عوض، ما می توانیم استفاده کنیم generateMetadata
عملکرد ایجاد ابرداده پویا برای هر صفحه.
// need to add the Metada type import
import type { Metadata } from "next";
// at the end of the file
export async function generateMetadata({ params }: Params): Promise<Metadata> {
const pokemon = await getPokemon(params.slug);
return {
title: `${pokemon.name} | Next.js + Pokemon`,
description: `${pokemon.name} | Next.js + Pokemon`,
openGraph: {
title: `${pokemon.name} | Next.js + Pokemon`,
description: `${pokemon.name} | Next.js + Pokemon`,
images: [
{
url: pokemon.sprites.front_default,
width: 400,
height: 400,
alt: pokemon.name,
},
],
},
};
}
اگرچه فهرست برنامه ویژگیهای بیشتری را در ترکیب با React به ارمغان میآورد یا فعال میکند، من در این مقاله به همه آنها نمیپردازم. این فقط برای مستندسازی تجربه من در تلاش برای این طرح بندی جدید بود که Next.js معرفی می کند. با این حال، با خیال راحت به بررسی و ذکر هر ویژگی که ارزش برجسته کردن را در نظرات میدانید، بپردازید.
من همچنین چند سبک به برنامه اضافه کردم و برنامه را اجرا کردم تا بتوانید آن را به صورت زنده ببینید. می توانید سایت زنده را در https://pokemon-app-directory.vercel.app بررسی کنید و مخزن را در https://github.com/ivanms1/pokemon-app-directory مشاهده کنید.
نتیجه
به طور کلی، من تجربه خوشایندی داشتم که دایرکتوری برنامه جدید را در Next.js امتحان کردم. در حالی که من قصد داشتم با طرح جدید آزمایش کنم، بیشتر مجذوب اجزای سرور و پتانسیل آنها برای ساده کردن توسعه شدم. با این حال، من در مورد اینکه اکوسیستم چقدر سریع با این ویژگی جدید سازگار می شود، نگرانی هایی دارم. یک جستجوی سریع نشان داد که بسیاری از کتابخانه ها هنوز از مولفه های سرور پشتیبانی نمی کنند و برخی برای پشتیبانی از آنها نیاز به تغییر ساختاری دارند.
با توجه به تغییر دایرکتوری صفحات به دایرکتوری برنامه، به نظر من این یک حرکت مثبت است. ناامیدکننده بود که هر فایلی که در پوشه pages ایجاد میشد به یک صفحه تبدیل میشد، و میدانم که بسیاری دیگر راهحلهایی برای ایجاد ساختار پوشهای شبیه صفحه داشتند. با این وجود، فکر نمیکنم هیچ چیز سختی وجود داشته باشد که مهاجرت را دردسرساز کند. من قالبها و فایلهای طرحبندی را عمیقاً بررسی نکردم، اما مطمئن هستم که برای یک برنامه بزرگتر مفید خواهند بود.
فعلاً همین است، ممنون که خواندید! اگر این مقاله برای شما مفید بود، لطفاً آن را به اشتراک بگذارید و آن را لایک کنید. همچنین برای مقالات بیشتر در آینده من را دنبال کنید.