برنامه نویسی

در حال امتحان کردن فهرست برنامه در 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 ایجاد می‌شد به یک صفحه تبدیل می‌شد، و می‌دانم که بسیاری دیگر راه‌حل‌هایی برای ایجاد ساختار پوشه‌ای شبیه صفحه داشتند. با این وجود، فکر نمی‌کنم هیچ چیز سختی وجود داشته باشد که مهاجرت را دردسرساز کند. من قالب‌ها و فایل‌های طرح‌بندی را عمیقاً بررسی نکردم، اما مطمئن هستم که برای یک برنامه بزرگ‌تر مفید خواهند بود.

فعلاً همین است، ممنون که خواندید! اگر این مقاله برای شما مفید بود، لطفاً آن را به اشتراک بگذارید و آن را لایک کنید. همچنین برای مقالات بیشتر در آینده من را دنبال کنید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا