برنامه نویسی

نحوه ایجاد یک وبلاگ با استفاده از NextJS v14 و MDX: یک راهنمای جامع

Summarize this content to 400 words in Persian Lang
توسعه یک وبلاگ بسیار موثر است زیرا به نمایش و به اشتراک گذاشتن دانش کسب شده، تجربیات مربوطه و به روز رسانی ها برای مخاطبان بزرگتر کمک می کند. اخیراً، من یک عملکرد وبلاگ را در وب‌سایت خود با NextJS v14، MDX و دیگر لیب‌ها ادغام کردم. این پست وبلاگ شما را از طریق مراحلی که برای ترکیب وبلاگ دارای بخش های به روز رسانی و همچنین پیکربندی Next دنبال کردم، راهنمایی می کند. js و همچنین اضافه کردن تمام وابستگی های مورد نیاز.

چرا وبلاگ نویسی را انتخاب کردم

بنابراین، با تجربه پروژه‌های واقعی، این وبلاگ را شروع کردم تا نگاهی باز به فرآیند کار داشته باشم و تفکر و اقداماتم را هنگام تبدیل مفاهیم به محصولات ملموس و همچنین دلایلم برای آن اقدامات شرح دهم. من که خودم یک توسعه‌دهنده هستم، بیشتر اوقات روی پروژه‌هایی تمرکز می‌کنم که در آن یک برنامه کاربردی به عنوان یک ایده صرف در ذهن توسعه‌دهنده و در واقعیت ملموس در مدت زمان نسبتاً کوتاهی شروع می‌شود. مستندسازی این سفر چندین هدف را دنبال می کند:

🕵️‍♂️ شفافیت: برای توضیح بیشتر، پاراگراف‌های زیر اقداماتی را که من برای اطمینان از کارآمد و مؤثر بودن پروژه‌هایم انتخاب می‌کنم تشریح می‌کند. از یک سو، برای توسعه‌دهنده مشتاق، اغلب اوقات مشاهده این که چگونه یک همکار با تجربه‌تر یا هم‌شاگردی، حسب مورد، در حال حل مشکل است، مفید است.
💡 الهام بخش: به اشتراک گذاشتن انگیزه ها و دلایل پشت پروژه هایم می تواند دیگران را ترغیب کند تا ایده های خود را دنبال کنند. درک “چرا” پشت یک پروژه اغلب سوخت مورد نیاز برای عبور از چالش ها و متعهد ماندن را فراهم می کند.
📚 مستندات: ثبت سابقه سفر توسعه ام به من کمک می کند پیشرفت خود را پیگیری کنم و در مورد درس های آموخته شده فکر کنم. این یک منبع ارزشمند برای مراجعات آینده و بهبود مستمر است.
🗣️ تعامل با جامعه: وبلاگ ارتباط دو طرفه را آسان می کند و بازخورد خوانندگان را دریافت می کند. همچنین با ارائه نظرات داستان ها و مقالات مختلف برای دریافت ایده های جدید، همکاری و همراهی سایر خوانندگان تعامل وجود دارد.

هدف من یادداشت کردن و به اشتراک گذاشتن تمام مراحل شکل‌گیری ایده و تبدیل آن به یک پروژه واقعی و در نتیجه ایجاد انگیزه در افراد برای به اشتراک گذاشتن ایده‌هایشان است. این راه من برای بازگرداندن چیزی به جمعیت توسعه دهندگان و کمک به ایجاد پایگاه دانش است.

خب… چطور انجامش دادم؟

افزودن و پیکربندی وابستگی ها

Next.js از MDX (Markdown برای JSX) خارج از جعبه با برخی تنظیمات اضافی پشتیبانی می کند. در اینجا نحوه تنظیم آن است:

بسته های مورد نیاز را نصب کنید

من بسته های ضروری MDX و وابستگی های مرتبط را نصب کردم:

npm install @mdx-js/loader @mdx-js/react @next/mdx @tailwindcss/typography

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به روز رسانی next.config.js

باید افزونه withMDX را به فایل پیکربندی Next.js اضافه کنیم.

// next.config.js
const withMDX = require(“@next/mdx”)();

const nextConfig = {
// Rest of the configuration
pageExtensions: [“js”, “jsx”, “mdx”, “ts”, “tsx”],
};

module.exports = withMDX(nextConfig);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به روز رسانی tailwindcss.config.ts

من از tailwind استفاده می کنم، بنابراین باید افزونه تایپوگرافی را به فایل پیکربندی tailwind اضافه کنم.

// tailwindcss.config.ts
const config = {
// Rest of the configuration
plugins: [require(“@tailwindcss/typography”)],
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجزای مورد نیاز را برای رندر کردن MDX ایجاد کنید

ما یک فایل mdxComponents ایجاد خواهیم کرد که به ما امکان می دهد نحوه نمایش هر عنصر MDX را تعریف کنیم.

// components/MdxComponents.tsxx
import Link from “next/link”;
import { MDXComponents } from “mdx/types”;
import { Ref, RefAttributes } from “react”;
import { Code } from “bright”;
export const mdxComponents: MDXComponents = {
pre: (props) => (
Code
theme={“github-dark”}
{…props}
style={{
margin: 0,
}}
/>
),
a: ({ children, ref, …props }) => {
return (
Link href={props.href || “.”} ref={ref as RefHTMLAnchorElement> | undefined} {…props}>
{children}
Link>
);
},
File: ({ children, path, …props }) => {
return (
div className=”bg-gray-950 pt-1 rounded-3xl”>
div className=”flex items-center ml-4 my-2 italic font-semibold”>{path}div>
{children}
div>
);
},
};

export default mdxComponents;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به عنوان مثال در کد بالا، ما در حال تعریف چگونگی pre تگ ارائه خواهد شد، ما از آن استفاده می کنیم Code جزء از bright کتابخانه ای برای ارائه بلوک های کد با برجسته سازی نحو. ما همچنین در حال تعریف چگونگی a تگ ارائه خواهد شد، ما از آن استفاده می کنیم Link جزء از Next.js برای رندر کردن پیوندها. ما هم داریم یک عرف تعریف می کنیم File جزء که یک مسیر فایل را در بالای بلوک کد ارائه می کند.

مؤلفه File دقیقاً همان چیزی است که من برای رندر کردن بلوک های کد در این پست وبلاگ استفاده می کنم!

بیایید کامپوننت را برای رندر MDX ایجاد کنیم!

// components/BlogCard.tsxx
import { MDXRemote } from “next-mdx-remote/rsc”;
import remarkGfm from “remark-gfm”;
import rehypeSlug from “rehype-slug”;
import rehypeAutolinkHeadings from “rehype-autolink-headings”;
import remarkA11yEmoji from “@fec/remark-a11y-emoji”;
import remarkToc from “remark-toc”;
import mdxComponents from “./MdxComponents”;

export default function BlogPost({ children }: { children: string }) {
return (
div className=”prose prose-invert min-w-full”>
MDXRemote
source={children}
options={{
mdxOptions: {
remarkPlugins: [
// Adds support for GitHub Flavored Markdown
remarkGfm,
// Makes emoji accessible ! adding aria-label
remarkA11yEmoji,
// generates a table of contents based on headings
[remarkToc, { tight: true }],
],
// These work together to add IDs and linkify headings
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings],
},
}}
components={mdxComponents}
/>
div>
);
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این مؤلفه ای است که پست وبلاگ را ارائه می دهد، از آن استفاده می کند MDXRemote جزء از next-mdx-remote/rsc برای ارائه محتوای MDX. ما همچنین برخی از گزینه ها را به MDXRemote مؤلفه ای برای فعال کردن پشتیبانی از GitHub Flavored Markdown، ایموجی های قابل دسترس و تولید فهرست مطالب. این mdxComponents شی شامل اجزایی است که برای ارائه محتوای MDX استفاده می شود.

منطقی برای واکشی پست های وبلاگ ایجاد کنید

ما انواع پست های وبلاگ را تعریف می کنیم و یک تابع برای واکشی همه پست ها ایجاد می کنیم.

// types.d.ts
export type IBlogPost = {
date: string;
title: string;
description: string;
slug: string;
tags: string[];
body: string;
};

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما خود را ذخیره خواهیم کرد .mdx فایل های زیر مسیر /posts است و ما از آن استفاده خواهیم کرد gray-matter کتابخانه برای تجزیه موضوع جلویی هر فایل.یک فایل برای تعریف توابع برای واکشی همه پست های وبلاگ ایجاد کنید.

// lib/blog.ts
import matter from “gray-matter”;
import path from “path”;
import fs from “fs/promises”;
import { cache } from “react”;
import { IBlogPost } from “@/types”;
export const getPosts: () => PromiseIBlogPost[]> = cache(async () => {
const posts = await fs.readdir(“./posts/”);

return Promise.all(
posts
.filter((file) => path.extname(file) === “.mdx”)
.map(async (file) => {
const filePath = `./posts/${file}`;
const postContent = await fs.readFile(filePath, “utf8”);
const { data, content } = matter(postContent);

// Not published? No problem, don’t show it.
if (data.published === false) {
return undefined;
}

return { …data, body: content } as IBlogPost;
})
.filter((e) => e)
) as PromiseIBlogPost[]>;
});

export async function getPost(slug: string) {
const posts = await getPosts();
return posts.find((post) => post?.slug === slug);
}

export default getPosts;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این getPosts تابع همه فایل‌های موجود در پوشه /posts را می‌خواند، فایل‌های غیر MDX را فیلتر می‌کند و با استفاده از آن، موضوع جلویی را تجزیه می‌کند. gray-matter. سپس آرایه ای از اشیاء حاوی داده های پست و محتوای بدنه را برمی گرداند. این getPost تابع یک پست خاص را بر اساس اسلاگ خود واکشی می کند.

یک صفحه وبلاگ ایجاد کنید

حالا بیایید صفحه ای را ایجاد کنیم که در آن همه پست های وبلاگ را نمایش می دهیم،من یک گروه ایجاد کردم تا بتوانم یک طرح بندی برای صفحات وبلاگ تعریف کنم، اگر به آن نیاز ندارید، نیازی به آن ندارید.

// app/(blog)/blog/page.tsxx
// Here’s where we will display all the blog posts
import BlogCard from “@/components/BlogCard”;
import getPosts from “@/lib/blog”;

export default async function PostPage() {
const posts = await getPosts();

return (

h1 className=”text-5xl”>
The span className=”font-bold”>Blogspan>.
h1>
div className=”flex flex-col space-y-10 mt-4 p-5″>
div>
ol className=”group/list”>
{posts.map((post, i) => (
li
className={`mb-12 animate-ease-in animate-delay-500 ${i % 2 == 0 ? “animate-fade-right” : “animate-fade-left”}`}
key={i}
>
{/* Remember to always define a key when doing a map function.*/}
BlogCard {…post} key={i} />
li>
))}
ol>
div>
div>
>
);
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این PostPage مؤلفه تمام پست های وبلاگ را با استفاده از getPosts تابع و نقشه هایی روی آنها برای ارائه a BlogCard جزء برای هر پست این BlogCard کامپوننت عنوان پست، توضیحات و برچسب ها را نمایش می دهد.

و سپس می توانیم صفحه ای را برای پست خاص ایجاد کنیم.

// app/(blog)/[slug]/page.tsxx
import BlogPost from “@/components/BlogPost”;
import getPosts, { getPost } from “@/lib/blog”;

import { notFound } from “next/navigation”;
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({ slug: post?.slug }));
}
export default async function PostPage({
params,
}: {
params: {
slug: string;
};
}) {
const post = await getPost(params.slug);
if (!post) return notFound();
return BlogPost>{post?.body}BlogPost>;
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این PostPage کامپوننت پست خاص را بر اساس اسلگ ارائه شده در URL واکشی می کند. اگر پست پیدا نشد، صفحه 404 را با استفاده از notFound تابع از next/navigation. این BlogPost کامپوننت محتوای پست را با استفاده از MDXRemote جزء.

یک نقشه سایت ایجاد کنید

ایجاد نقشه سایت برای بهینه سازی موتورهای جستجو (SEO) ضروری است و به موتورهای جستجو کمک می کند تا صفحات وب سایت شما را کشف و فهرست کنند. ما می توانیم با استفاده از یک تابع بدون سرور در Next.js یک نقشه سایت ایجاد کنیم.

// app/sitemap.ts
import { getPosts } from “@/lib/blog”;

export default async function sitemap() {
// Define the routes that should be included in the sitemap
const routes = [“”, “/blog”].map((route) => ({
url: `https://ginos.codes${route}`,
lastModified: new Date().toISOString().split(“T”)[0],
}));

// Get all posts and create a sitemap route for each one
const posts = await getPosts();
const blogs = posts.map((post) => ({
url: `https://ginos.codes/blog/${post.slug}`,
lastModified: new Date(post.date).toISOString().split(“T”)[0],
}));

return […routes, …blogs];
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این sitemap تابع مسیرهایی را که باید در نقشه سایت گنجانده شود را تعریف می کند. این شامل صفحه اصلی و صفحه وبلاگ است. سپس تمام پست های وبلاگ را واکشی می کند و یک مسیر نقشه سایت برای هر پست ایجاد می کند، از جمله URL پست و آخرین تاریخ اصلاح.

نتیجه

در این راهنما، ما روند کامل راه اندازی یک وبلاگ را با استفاده از NextJS v14 و MDX پوشش دادیم. از نصب و پیکربندی وابستگی‌های لازم گرفته تا ایجاد و نمایش پست‌های وبلاگ، هر مرحله برای یک وبلاگ کاربردی و زیبایی‌شناختی بسیار مهم است. با دنبال کردن این مراحل، می‌توانید به راحتی وبلاگی راه‌اندازی کنید که نه تنها مدیریت آن آسان است، بلکه سئو پسند نیز باشد.

توسعه یک وبلاگ بسیار موثر است زیرا به نمایش و به اشتراک گذاشتن دانش کسب شده، تجربیات مربوطه و به روز رسانی ها برای مخاطبان بزرگتر کمک می کند. اخیراً، من یک عملکرد وبلاگ را در وب‌سایت خود با NextJS v14، MDX و دیگر لیب‌ها ادغام کردم. این پست وبلاگ شما را از طریق مراحلی که برای ترکیب وبلاگ دارای بخش های به روز رسانی و همچنین پیکربندی Next دنبال کردم، راهنمایی می کند. js و همچنین اضافه کردن تمام وابستگی های مورد نیاز.

چرا وبلاگ نویسی را انتخاب کردم

بنابراین، با تجربه پروژه‌های واقعی، این وبلاگ را شروع کردم تا نگاهی باز به فرآیند کار داشته باشم و تفکر و اقداماتم را هنگام تبدیل مفاهیم به محصولات ملموس و همچنین دلایلم برای آن اقدامات شرح دهم. من که خودم یک توسعه‌دهنده هستم، بیشتر اوقات روی پروژه‌هایی تمرکز می‌کنم که در آن یک برنامه کاربردی به عنوان یک ایده صرف در ذهن توسعه‌دهنده و در واقعیت ملموس در مدت زمان نسبتاً کوتاهی شروع می‌شود. مستندسازی این سفر چندین هدف را دنبال می کند:

  1. 🕵️‍♂️ شفافیت: برای توضیح بیشتر، پاراگراف‌های زیر اقداماتی را که من برای اطمینان از کارآمد و مؤثر بودن پروژه‌هایم انتخاب می‌کنم تشریح می‌کند. از یک سو، برای توسعه‌دهنده مشتاق، اغلب اوقات مشاهده این که چگونه یک همکار با تجربه‌تر یا هم‌شاگردی، حسب مورد، در حال حل مشکل است، مفید است.

  2. 💡 الهام بخش: به اشتراک گذاشتن انگیزه ها و دلایل پشت پروژه هایم می تواند دیگران را ترغیب کند تا ایده های خود را دنبال کنند. درک “چرا” پشت یک پروژه اغلب سوخت مورد نیاز برای عبور از چالش ها و متعهد ماندن را فراهم می کند.

  3. 📚 مستندات: ثبت سابقه سفر توسعه ام به من کمک می کند پیشرفت خود را پیگیری کنم و در مورد درس های آموخته شده فکر کنم. این یک منبع ارزشمند برای مراجعات آینده و بهبود مستمر است.

  4. 🗣️ تعامل با جامعه: وبلاگ ارتباط دو طرفه را آسان می کند و بازخورد خوانندگان را دریافت می کند. همچنین با ارائه نظرات داستان ها و مقالات مختلف برای دریافت ایده های جدید، همکاری و همراهی سایر خوانندگان تعامل وجود دارد.

هدف من یادداشت کردن و به اشتراک گذاشتن تمام مراحل شکل‌گیری ایده و تبدیل آن به یک پروژه واقعی و در نتیجه ایجاد انگیزه در افراد برای به اشتراک گذاشتن ایده‌هایشان است. این راه من برای بازگرداندن چیزی به جمعیت توسعه دهندگان و کمک به ایجاد پایگاه دانش است.

خب… چطور انجامش دادم؟

افزودن و پیکربندی وابستگی ها

Next.js از MDX (Markdown برای JSX) خارج از جعبه با برخی تنظیمات اضافی پشتیبانی می کند. در اینجا نحوه تنظیم آن است:

بسته های مورد نیاز را نصب کنید

من بسته های ضروری MDX و وابستگی های مرتبط را نصب کردم:

npm install @mdx-js/loader @mdx-js/react @next/mdx @tailwindcss/typography 
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به روز رسانی next.config.js

باید افزونه withMDX را به فایل پیکربندی Next.js اضافه کنیم.

// next.config.js
const withMDX = require("@next/mdx")();

const nextConfig = {
  // Rest of the configuration
  pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
};

module.exports = withMDX(nextConfig);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به روز رسانی tailwindcss.config.ts

من از tailwind استفاده می کنم، بنابراین باید افزونه تایپوگرافی را به فایل پیکربندی tailwind اضافه کنم.

// tailwindcss.config.ts
const config = {
  // Rest of the configuration
  plugins: [require("@tailwindcss/typography")],
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجزای مورد نیاز را برای رندر کردن MDX ایجاد کنید

ما یک فایل mdxComponents ایجاد خواهیم کرد که به ما امکان می دهد نحوه نمایش هر عنصر MDX را تعریف کنیم.

// components/MdxComponents.tsxx
import Link from "next/link";
import { MDXComponents } from "mdx/types";
import { Ref, RefAttributes } from "react";
import { Code } from "bright";
export const mdxComponents: MDXComponents = {
  pre: (props) => (
    Code
      theme={"github-dark"}
      {...props}
      style={{
        margin: 0,
      }}
    />
  ),
  a: ({ children, ref, ...props }) => {
    return (
      Link href={props.href || "."} ref={ref as RefHTMLAnchorElement> | undefined} {...props}>
        {children}
      Link>
    );
  },
  File: ({ children, path, ...props }) => {
    return (
      div className="bg-gray-950 pt-1 rounded-3xl">
        div className="flex items-center ml-4 my-2 italic font-semibold">{path}div>
        {children}
      div>
    );
  },
};

export default mdxComponents;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به عنوان مثال در کد بالا، ما در حال تعریف چگونگی pre تگ ارائه خواهد شد، ما از آن استفاده می کنیم Code جزء از bright کتابخانه ای برای ارائه بلوک های کد با برجسته سازی نحو. ما همچنین در حال تعریف چگونگی a تگ ارائه خواهد شد، ما از آن استفاده می کنیم Link جزء از Next.js برای رندر کردن پیوندها. ما هم داریم یک عرف تعریف می کنیم File جزء که یک مسیر فایل را در بالای بلوک کد ارائه می کند.

مؤلفه File دقیقاً همان چیزی است که من برای رندر کردن بلوک های کد در این پست وبلاگ استفاده می کنم!

بیایید کامپوننت را برای رندر MDX ایجاد کنیم!

// components/BlogCard.tsxx
import { MDXRemote } from "next-mdx-remote/rsc";
import remarkGfm from "remark-gfm";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import remarkA11yEmoji from "@fec/remark-a11y-emoji";
import remarkToc from "remark-toc";
import mdxComponents from "./MdxComponents";

export default function BlogPost({ children }: { children: string }) {
  return (
    div className="prose prose-invert min-w-full">
      MDXRemote
        source={children}
        options={{
          mdxOptions: {
            remarkPlugins: [
              // Adds support for GitHub Flavored Markdown
              remarkGfm,
              // Makes emoji accessible ! adding aria-label
              remarkA11yEmoji,
              // generates a table of contents based on headings
              [remarkToc, { tight: true }],
            ],
            // These work together to add IDs and linkify headings
            rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings],
          },
        }}
        components={mdxComponents}
      />
    div>
  );
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این مؤلفه ای است که پست وبلاگ را ارائه می دهد، از آن استفاده می کند MDXRemote جزء از next-mdx-remote/rsc برای ارائه محتوای MDX. ما همچنین برخی از گزینه ها را به MDXRemote مؤلفه ای برای فعال کردن پشتیبانی از GitHub Flavored Markdown، ایموجی های قابل دسترس و تولید فهرست مطالب. این mdxComponents شی شامل اجزایی است که برای ارائه محتوای MDX استفاده می شود.

منطقی برای واکشی پست های وبلاگ ایجاد کنید

ما انواع پست های وبلاگ را تعریف می کنیم و یک تابع برای واکشی همه پست ها ایجاد می کنیم.

// types.d.ts
export type IBlogPost = {
  date: string;
  title: string;
  description: string;
  slug: string;
  tags: string[];
  body: string;
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما خود را ذخیره خواهیم کرد .mdx فایل های زیر مسیر /posts است و ما از آن استفاده خواهیم کرد gray-matter کتابخانه برای تجزیه موضوع جلویی هر فایل.
یک فایل برای تعریف توابع برای واکشی همه پست های وبلاگ ایجاد کنید.

// lib/blog.ts  
import matter from "gray-matter";
import path from "path";
import fs from "fs/promises";
import { cache } from "react";
import { IBlogPost } from "@/types";
export const getPosts: () => PromiseIBlogPost[]> = cache(async () => {
  const posts = await fs.readdir("./posts/");

  return Promise.all(
    posts
      .filter((file) => path.extname(file) === ".mdx")
      .map(async (file) => {
        const filePath = `./posts/${file}`;
        const postContent = await fs.readFile(filePath, "utf8");
        const { data, content } = matter(postContent);

        // Not published? No problem, don't show it.
        if (data.published === false) {
          return undefined;
        }

        return { ...data, body: content } as IBlogPost;
      })
      .filter((e) => e)
  ) as PromiseIBlogPost[]>;
});

export async function getPost(slug: string) {
  const posts = await getPosts();
  return posts.find((post) => post?.slug === slug);
}

export default getPosts;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این getPosts تابع همه فایل‌های موجود در پوشه /posts را می‌خواند، فایل‌های غیر MDX را فیلتر می‌کند و با استفاده از آن، موضوع جلویی را تجزیه می‌کند. gray-matter. سپس آرایه ای از اشیاء حاوی داده های پست و محتوای بدنه را برمی گرداند. این getPost تابع یک پست خاص را بر اساس اسلاگ خود واکشی می کند.

یک صفحه وبلاگ ایجاد کنید

حالا بیایید صفحه ای را ایجاد کنیم که در آن همه پست های وبلاگ را نمایش می دهیم،
من یک گروه ایجاد کردم تا بتوانم یک طرح بندی برای صفحات وبلاگ تعریف کنم، اگر به آن نیاز ندارید، نیازی به آن ندارید.

// app/(blog)/blog/page.tsxx
// Here's where we will display all the blog posts
import BlogCard from "@/components/BlogCard";
import getPosts from "@/lib/blog";

export default async function PostPage() {
  const posts = await getPosts();

  return (
    
      h1 className="text-5xl">
        The span className="font-bold">Blogspan>.
      h1>
      div className="flex flex-col space-y-10 mt-4 p-5">
        div>
          ol className="group/list">
            {posts.map((post, i) => (
              li
                className={`mb-12 animate-ease-in animate-delay-500 ${i % 2 == 0 ? "animate-fade-right" : "animate-fade-left"}`}
                key={i}
              >
              {/* Remember to always define a key when doing a map function.*/}
                BlogCard {...post} key={i} />
              li>
            ))}
          ol>
        div>
      div>
    >
  );
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این PostPage مؤلفه تمام پست های وبلاگ را با استفاده از getPosts تابع و نقشه هایی روی آنها برای ارائه a BlogCard جزء برای هر پست این BlogCard کامپوننت عنوان پست، توضیحات و برچسب ها را نمایش می دهد.

و سپس می توانیم صفحه ای را برای پست خاص ایجاد کنیم.

// app/(blog)/[slug]/page.tsxx
import BlogPost from "@/components/BlogPost";
import getPosts, { getPost } from "@/lib/blog";

import { notFound } from "next/navigation";
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map((post) => ({ slug: post?.slug }));
}
export default async function PostPage({
  params,
}: {
  params: {
    slug: string;
  };
}) {
  const post = await getPost(params.slug);
  if (!post) return notFound();
  return BlogPost>{post?.body}BlogPost>;
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این PostPage کامپوننت پست خاص را بر اساس اسلگ ارائه شده در URL واکشی می کند. اگر پست پیدا نشد، صفحه 404 را با استفاده از notFound تابع از next/navigation. این BlogPost کامپوننت محتوای پست را با استفاده از MDXRemote جزء.

یک نقشه سایت ایجاد کنید

ایجاد نقشه سایت برای بهینه سازی موتورهای جستجو (SEO) ضروری است و به موتورهای جستجو کمک می کند تا صفحات وب سایت شما را کشف و فهرست کنند. ما می توانیم با استفاده از یک تابع بدون سرور در Next.js یک نقشه سایت ایجاد کنیم.

// app/sitemap.ts
import { getPosts } from "@/lib/blog";

export default async function sitemap() {
  // Define the routes that should be included in the sitemap
  const routes = ["", "/blog"].map((route) => ({
    url: `https://ginos.codes${route}`,
    lastModified: new Date().toISOString().split("T")[0],
  }));

  // Get all posts and create a sitemap route for each one
  const posts = await getPosts();
  const blogs = posts.map((post) => ({
    url: `https://ginos.codes/blog/${post.slug}`,
    lastModified: new Date(post.date).toISOString().split("T")[0],
  }));

  return [...routes, ...blogs];
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این sitemap تابع مسیرهایی را که باید در نقشه سایت گنجانده شود را تعریف می کند. این شامل صفحه اصلی و صفحه وبلاگ است. سپس تمام پست های وبلاگ را واکشی می کند و یک مسیر نقشه سایت برای هر پست ایجاد می کند، از جمله URL پست و آخرین تاریخ اصلاح.

نتیجه

در این راهنما، ما روند کامل راه اندازی یک وبلاگ را با استفاده از NextJS v14 و MDX پوشش دادیم. از نصب و پیکربندی وابستگی‌های لازم گرفته تا ایجاد و نمایش پست‌های وبلاگ، هر مرحله برای یک وبلاگ کاربردی و زیبایی‌شناختی بسیار مهم است. با دنبال کردن این مراحل، می‌توانید به راحتی وبلاگی راه‌اندازی کنید که نه تنها مدیریت آن آسان است، بلکه سئو پسند نیز باشد.

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

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

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

همچنین ببینید
بستن
دکمه بازگشت به بالا