اتصال وردپرس به Next.js یک معماری Headless (بی‌سر) است که در آن WordPress به‌عنوان سیستم مدیریت محتوا (CMS) و Next.js به‌عنوان لایه نمایش، از طریق REST API یا WPGraphQL با یکدیگر ارتباط برقرار می‌کنند. Next.js یک فریم‌ورک React است که توسط Vercel توسعه یافته و با پشتیبانی از Server-Side Rendering (SSR)، Static Site Generation (SSG)، و Incremental Static Regeneration (ISR)، امکان ساخت سایت‌های سریع و مقیاس‌پذیر را فراهم می‌کند. در این معماری، تیم محتوا همچنان از پنل آشنای وردپرس استفاده می‌کند و کاربران نهایی تجربه‌ای مدرن و پرسرعت دریافت می‌کنند. اگر با مقایسه REST API و GraphQL در وردپرس آشنا باشید، می‌دانید که انتخاب روش اتصال، اولین تصمیم معماری است که بر کل پروژه اثر می‌گذارد.

در یک پروژه فروشگاهی با ترافیک روزانه بالا، تیم محتوا از سرعت پایین پنل وردپرس و زمان بارگذاری کند صفحات شکایت داشت. بعد از مهاجرت به Next.js، همان محتوا با ISR (Incremental Static Regeneration) به صفحاتی با زمان پاسخ زیر ۲۰۰ میلی‌ثانیه تبدیل شد و بار سرور وردپرس به یک‌دهم کاهش یافت. این تجربه، هسته اصلی جذابیت معماری Headless را نشان می‌دهد.

چرا Next.js برای Headless WordPress انتخاب می‌شود؟

Next.js یکی از محبوب‌ترین فریم‌ورک‌های React است که از سال ۲۰۱۶ توسط Vercel توسعه می‌یابد. این فریم‌ورک با ترکیب React، Webpack، و Babel، یک تجربه توسعه یکپارچه فراهم می‌کند و از چندین استراتژی رندر پشتیبانی می‌نماید. ترکیب Next.js با WordPress، الگوی Headless CMS را پیاده‌سازی می‌کند که در آن، WordPress مسئول مدیریت محتوا و Next.js مسئول نمایش آن است. اگر با مفاهیم پایه فرانت‌اند و نحوه کار آن آشنا شده باشید، این جداسازی را به‌عنوان یک الگوی معماری مدرن می‌شناسید.

مزیت اول Next.js، تنوع استراتژی‌های رندر است. برخلاف برخی فریم‌ورک‌ها که فقط یک مدل رندر پشتیبانی می‌کنند، Next.js به شما اجازه می‌دهد برای هر صفحه تصمیم بگیرید که SSG، ISR، SSR، یا Client-Side Rendering (CSR) استفاده شود. این انعطاف‌پذیری در ترکیب با WordPress، بهینه‌سازی دقیقی را ممکن می‌سازد: صفحات وبلاگ با SSG برای سرعت حداکثری، صفحات فروشگاه با ISR برای تعادل بین سرعت و تازگی، و داشبورد کاربر با SSR برای محتوای شخصی‌سازی‌شده.

مزیت دوم، یکپارچگی بومی با Vercel است. Vercel پلتفرم استقراری است که توسط تیم Next.js ساخته شده و بهینه‌سازی‌های عمیقی برای این فریم‌ورک دارد. استقرار Next.js روی Vercel، فرآیند پیچیده‌ای مثل Build، CDN Distribution، و Edge Functions را به یکپارچگی خودکار تبدیل می‌کند. اگر با نقش CDN در بهبود سرعت سایت آشنا شده باشید، می‌دانید که این یکپارچگی، تفاوت محسوسی در TTFB (Time to First Byte) ایجاد می‌کند.

«ترکیب Next.js و WordPress یک تصمیم معمارانه است: WordPress را برای چیزی که در آن بهترین است نگه می‌دارید، و نمایش را به لایه‌ای می‌سپارید که در آن بهترین است.»

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

مزیت چهارم، پشتیبانی از App Router و React Server Components (RSC) است. از Next.js 13 به بعد، App Router معرفی شد که مدل رندر جدیدی بر پایه Server Components ارائه می‌دهد. این مدل، داده‌ها را در سمت سرور Fetch می‌کند و فقط HTML و Interactivity موردنیاز را به کلاینت می‌فرستد. نتیجه، کاهش حجم JavaScript و بهبود Core Web Vitals است. اگر با روش‌های بهبود Core Web Vitals آشنا شده باشید، می‌دانید که این مدل مستقیماً بر LCP و INP اثر مثبت می‌گذارد.

معماری Next.js و WordPress: از Monolith تا Headless

در معماری سنتی WordPress، تمام لایه‌ها در یک سرور PHP اجرا می‌شوند: مدیریت محتوا، Query دیتابیس، رندر HTML، و ارسال پاسخ. این معماری Monolithic (یکپارچه) ساده است اما محدودیت‌های مقیاس‌پذیری دارد. در معماری Headless با Next.js، این لایه‌ها از هم جدا می‌شوند:

لایه مسئولیت فناوری
Content Management ایجاد و مدیریت محتوا WordPress Admin
Data Layer ارائه داده از طریق API WordPress REST API / WPGraphQL
Presentation Layer رندر HTML و UI Next.js (SSG/ISR/SSR)
Distribution Layer توزیع محتوا در لبه شبکه Vercel Edge Network / CDN
Client Layer تعامل کاربر React Client Components

این جداسازی، مزایای روشنی دارد. اول، استقلال تیم‌ها: تیم محتوا در WordPress کار می‌کند و تیم فرانت‌اند در Next.js، بدون تداخل. دوم، مقیاس‌پذیری مستقل: اگر ترافیک سایت افزایش یابد، فقط لایه Presentation نیاز به مقیاس‌بندی دارد، نه WordPress. سوم، امنیت: WordPress در پشت یک API محافظت‌شده قرار می‌گیرد و مستقیماً به اینترنت مواجه نمی‌شود. اگر با روش‌های امن‌سازی REST API آشنا شده باشید، این لایه‌بندی را به‌عنوان یک مزیت امنیتی می‌شناسید.

نکته مهم این است که در معماری Headless، WordPress باید به‌عنوان یک API Server بهینه شود، نه یک وب‌سایت سنتی. این یعنی: غیرفعال کردن قالب‌های غیرضروری، محدود کردن افزونه‌ها به موارد ضروری، و پیکربندی CORS (Cross-Origin Resource Sharing) برای اجازه دسترسی Next.js. اگر با راهنمای کامل REST API در وردپرس آشنا شده باشید، این بهینه‌سازی‌ها را به‌عنوان بخشی از راه‌اندازی Headless می‌شناسید.

App Router در برابر Pages Router

Next.js دو Router دارد: Pages Router (نسخه قدیمی‌تر) و App Router (نسخه جدید از Next.js 13). انتخاب بین این دو، یک تصمیم معماری مهم است که بر ساختار پروژه، مدل داده‌کشی، و عملکرد نهایی اثر می‌گذارد.

Pages Router مدل سنتی Next.js است که بر پایه فایل‌های pages/ کار می‌کند. هر فایل یک صفحه است و از توابع getServerSideProps، getStaticProps، و getStaticPaths برای داده‌کشی استفاده می‌کند. این مدل، بالغ و پایدار است اما محدودیت‌هایی دارد: هر صفحه یک Component بزرگ است، Server Components پشتیبانی نمی‌شوند، و Layoutها به‌صورت خودکار Re-render می‌شوند.

App Router مدل جدید است که بر پایه پوشه app/ کار می‌کند. هر پوشه یک Route Segment است و می‌تواند شامل page.tsx، layout.tsx، loading.tsx، و error.tsx باشد. App Router از React Server Components پشتیبانی می‌کند، که به‌صورت پیش‌فرض تمام کامپوننت‌ها را در سرور رندر می‌کند و فقط کامپوننت‌های علامت‌گذاری‌شده با "use client" را به کلاینت می‌فرستد.

ویژگی Pages Router App Router
مدل رندر Client Components React Server Components
داده‌کشی getStaticProps / getServerSideProps async Component / fetch
Layout _app.tsx و _document.tsx layout.tsx تودرتو
Streaming محدود بومی با Suspense
Bundle Size بالاتر پایین‌تر (RSC)
یادگیری آشناتر مفهومی جدید

برای پروژه‌های جدید Headless با WordPress، App Router توصیه می‌شود چون مزایای روشنی دارد: کاهش Bundle Size، Streaming بومی، و Layoutهای تودرتو. برای پروژه‌های موجود که بر پایه Pages Router ساخته شده‌اند، مهاجرت به App Router می‌تواند تدریجی باشد. اگر با اتصال وردپرس به Remix آشنا شده باشید، می‌دانید که Remix نیز از یک مدل مشابه با Loader استفاده می‌کند و این رویکرد در فریم‌ورک‌های مدرن رایج شده است.

«App Router نه فقط یک Router جدید، بلکه یک مدل ذهنی جدید است: به‌جای «چه چیزی در کلاینت رندر شود»، بپرسید «چه چیزی باید در کلاینت رندر شود».»

اتصال به WordPress REST API

WordPress REST API از نسخه ۴.۷ در هسته قرار دارد و برای اتصال Next.js به آن، نیازی به افزونه اضافی نیست. Endpoint پیش‌فرض برای نوشته‌ها /wp-json/wp/v2/posts است. اولین گام، تنظیم متغیر محیطی برای آدرس WordPress است:

# .env.local
WORDPRESS_API_URL=https://cms.example.com

سپس یک ماژول کمکی برای Fetch کردن داده‌ها ایجاد می‌شود:

// lib/wordpress.ts
const API_URL = process.env.WORDPRESS_API_URL;

export async function fetchAPI(endpoint: string, params = {}) {
  const url = new URL(`${API_URL}/wp-json/wp/v2/${endpoint}`);
  Object.entries(params).forEach(([key, value]) => {
    url.searchParams.set(key, String(value));
  });

  const res = await fetch(url.toString(), {
    next: { revalidate: 60 },
  });

  if (!res.ok) {
    throw new Error(`WordPress API error: ${res.status}`);
  }

  return res.json();
}

پارامتر next: { revalidate: 60 } به Next.js می‌گوید که داده‌ها را به‌مدت ۶۰ ثانیه کش کند. این مکانیزم، Data Cache نامیده می‌شود و در App Router بومی است. اگر با ساختاردهی داده با JSON آشنا شده باشید، می‌دانید که REST API وردپرس داده‌ها را در قالب JSON برمی‌گرداند و Next.js آن‌ها را در Cache نگه می‌دارد.

دریافت نوشته‌ها با _embed

پارامتر _embed به REST API وردپرس می‌گوید که داده‌های مرتبط (نویسنده، تصویر شاخص، ترم‌ها) را در پاسخ جاسازی کند. این پارامتر از درخواست‌های اضافی جلوگیری می‌کند:

export async function getPosts(perPage = 10) {
  return fetchAPI('posts', {
    _embed: true,
    per_page: perPage,
    orderby: 'date',
    order: 'desc',
  });
}

پاسخ شامل یک آرایه از نوشته‌ها است که هرکدام فیلد _embedded دارد. این فیلد شامل author، wp:featuredmedia، و wp:term است. اگر با REST API در عمل: راهنمای ساخت، تست و نگهداری آشنا شده باشید، این ساختار برای شما آشناست.

صفحه‌بندی و مدیریت خطا

WordPress REST API از هدرهای X-WP-Total و X-WP-TotalPages برای صفحه‌بندی استفاده می‌کند. برای دسترسی به این هدرها در Next.js، باید Response را به‌طور کامل دریافت کنید:

export async function getPaginatedPosts(page = 1, perPage = 10) {
  const url = `${API_URL}/wp-json/wp/v2/posts?_embed&page=${page}&per_page=${perPage}`;
  const res = await fetch(url, { next: { revalidate: 60 } });

  if (!res.ok) {
    if (res.status === 400) {
      return { posts: [], total: 0, totalPages: 0 };
    }
    throw new Error(`API error: ${res.status}`);
  }

  return {
    posts: await res.json(),
    total: parseInt(res.headers.get('X-WP-Total') || '0'),
    totalPages: parseInt(res.headers.get('X-WP-TotalPages') || '0'),
  };
}

مدیریت خطای 400 مهم است چون WordPress وقتی page از totalPages بیشتر باشد، خطای rest_post_invalid_page_number برمی‌گرداند.

اتصال به WPGraphQL و Apollo Client

برای پروژه‌هایی که به WPGraphQL نیاز دارند، Next.js می‌تواند با Apollo Client یا یک Client سبک مثل graphql-request ادغام شود. مزیت GraphQL در این ترکیب، کاهش تعداد درخواست‌ها و دریافت دقیق داده‌های موردنیاز است.

نصب Apollo Client:

npm install @apollo/client graphql

سپس یک Client ساده برای استفاده در Server Components:

// lib/apollo-server.ts
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';

export function getClient() {
  return new ApolloClient({
    link: new HttpLink({
      uri: `${process.env.WORDPRESS_API_URL}/graphql`,
    }),
    cache: new InMemoryCache(),
    ssrMode: true,
  });
}

استفاده در یک Server Component:

// app/posts/page.tsx
import { gql } from '@apollo/client';
import { getClient } from '@/lib/apollo-server';

const GET_POSTS = gql`
  query GetPosts($first: Int!) {
    posts(first: $first) {
      nodes {
        id
        title
        slug
        excerpt
        featuredImage {
          node {
            sourceUrl
            altText
          }
        }
      }
    }
  }
`;

export default async function PostsPage() {
  const client = getClient();
  const { data } = await client.query({
    query: GET_POSTS,
    variables: { first: 10 },
    context: { fetchOptions: { next: { revalidate: 60 } } },
  });

  return (
    <ul>
      {data.posts.nodes.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

نکته مهم در Apollo Client با Server Components: نباید از ApolloProvider در سرور استفاده کرد. هر درخواست باید یک Client جدید بسازد تا از نشت داده بین کاربران جلوگیری شود. اگر با آموزش استفاده از GraphQL در وردپرس آشنا شده باشید، این الگو را به‌عنوان یک اصل امنیتی می‌شناسید.

«در Server Components، State سراسری یک ضدالگو است. هر درخواست باید Client مستقل خود را داشته باشد تا داده‌ها نشت نکنند.»

مقایسه REST و GraphQL در Next.js

انتخاب بین REST و GraphQL در Next.js به چند عامل بستگی دارد:

  • REST: ساده‌تر، Cache سطح HTTP بومی، مناسب برای پروژه‌های کوچک و متوسط
  • GraphQL: انعطاف‌پذیرتر، کاهش تعداد درخواست‌ها، مناسب برای پروژه‌های Headless با مصرف‌کنندگان متنوع

در Server Components، هر دو روش کار می‌کنند. مزیت REST در Next.js، یکپارچگی بومی با fetch و Data Cache است. مزیت GraphQL، امکان دریافت دقیق داده‌های تودرتو در یک درخواست است. اگر با مقایسه REST API و GraphQL در وردپرس آشنا شده باشید، این تصمیم را به‌عنوان یک انتخاب معمارانه می‌شناسید.

Server Components و استراتژی‌های Fetch

در App Router، کامپوننت‌ها به‌صورت پیش‌فرض Server Components هستند. این یعنی کد آن‌ها در سرور اجرا می‌شود و به دیتابیس، فایل سیستم، و APIهای داخلی دسترسی دارند. برای کامپوننت‌هایی که نیاز به تعامل کاربر دارند، باید از "use client" استفاده کرد.

// Server Component (پیش‌فرض)
async function PostList() {
  const posts = await getPosts();
  return <ul>{posts.map((p) => <li key={p.id}>{p.title.rendered}</li>)}</ul>;
}

// Client Component
'use client';
import { useState } from 'react';

function SearchBox() {
  const [query, setQuery] = useState('');
  return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
}

سه استراتژی Fetch در Next.js وجود دارد:

استراتژی کاربرد Revalidation
cache: 'force-cache' داده‌های ثابت (تنظیمات سایت) دستی با revalidatePath
next: { revalidate: 60 } داده‌های نیمه‌پویا (نوشته‌ها) خودکار هر ۶۰ ثانیه
cache: 'no-store' داده‌های پویا (سبد خرید) در هر درخواست

انتخاب استراتژی درست، تفاوت بین یک سایت سریع و یک سایت کند است. برای داده‌های وردپرس، الگوی رایج استفاده از revalidate با مقدار ۶۰ یا ۳۰۰ ثانیه است. اگر با بهینه‌سازی عملکرد REST API آشنا شده باشید، می‌دانید که این لایه‌بندی Cache، کلید مقیاس‌پذیری است.

SSG، ISR و On-Demand Revalidation

Next.js سه مدل اصلی رندر برای صفحات دارد: SSG، ISR و SSR. انتخاب بین این سه، یک تصمیم معماری است که بر تازگی محتوا و سرعت نهایی اثر می‌گذارد.

SSG (Static Site Generation): صفحه در زمان Build یک‌بار تولید می‌شود و برای همه کاربران یکسان است. این مدل، سریع‌ترین گزینه است اما محتوا در زمان Build قفل می‌شود. برای سایت‌هایی با محتوای ثابت (مستندات، صفحات فرود) مناسب است.

ISR (Incremental Static Regeneration): صفحه در زمان Build تولید می‌شود اما Next.js در پس‌زمینه، پس از مدت مشخصی آن را بازتولید می‌کند. این مدل، تعادل بین سرعت SSG و تازگی SSR را فراهم می‌کند:

// app/posts/[slug]/page.tsx
export const revalidate = 60; // بازتولید هر ۶۰ ثانیه

export async function generateStaticParams() {
  const posts = await getPosts(100);
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function PostPage({ params }) {
  const post = await getPostBySlug(params.slug);
  return <article><h1>{post.title.rendered}</h1></article>;
}

On-Demand Revalidation: به‌جای انتظار برای انقضای زمان، می‌توانید یک Webhook از WordPress ارسال کنید که Next.js را وادار به بازتولید صفحه کند. این الگو، Webhook-based Revalidation نامیده می‌شود و برای سایت‌های خبری یا فروشگاهی که محتوا به‌سرعت تغییر می‌کند، ایده‌آل است:

// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = request.nextUrl.searchParams.get('secret');
  if (secret !== process.env.REVALIDATE_SECRET) {
    return NextResponse.json({ error: 'Invalid secret' }, { status: 401 });
  }

  const body = await request.json();
  revalidatePath(`/posts/${body.slug}`);

  return NextResponse.json({ revalidated: true });
}

در سمت WordPress، یک Action در Hook save_post ثبت می‌شود که پس از انتشار نوشته، یک درخواست به این Endpoint ارسال می‌کند. اگر با هوک‌های وردپرس و نحوه کار آن‌ها آشنا شده باشید، این الگو را به‌عنوان یک یکپارچگی هوشمند می‌شناسید.

احراز هویت و Preview Mode

در معماری Headless، احراز هویت دو جنبه دارد: احراز هویت کاربران سایت (Login) و Preview Mode برای دیدن پیش‌نویس‌ها.

Preview Mode در Next.js

Preview Mode به تیم محتوا اجازه می‌دهد پیش از انتشار، نوشته را در سایت ببینند. این قابلیت با Draft Preview در WordPress کار می‌کند:

// app/api/preview/route.ts
import { draftMode } from 'next/headers';
import { redirect } from 'next/navigation';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const secret = searchParams.get('secret');
  const slug = searchParams.get('slug');

  if (secret !== process.env.PREVIEW_SECRET) {
    return new Response('Invalid token', { status: 401 });
  }

  draftMode().enable();
  redirect(`/posts/${slug}`);
}

در WordPress، یک لینک Preview در پنل مدیریت اضافه می‌شود که به این Endpoint اشاره می‌کند. این الگو، تجربه تیم محتوا را حفظ می‌کند و از سردرگمی جلوگیری می‌نماید.

احراز هویت کاربران

برای احراز هویت کاربران، دو رویکرد رایج وجود دارد: JWT (JSON Web Token) و Session-based. در Next.js، JWT رایج‌تر است چون با Server Components و Edge Functions سازگارتر است. اگر با پیاده‌سازی JWT در APIهای مدرن آشنا شده باشید، این الگو برای شما آشناست.

رویکرد توصیه‌شده: احراز هویت در سمت Next.js با NextAuth.js انجام می‌شود و WordPress فقط به‌عنوان منبع داده استفاده می‌شود. در این مدل، WordPress نیازی به مدیریت Session ندارد و فقط Application Passwords یا JWT را تأیید می‌کند.

بهینه‌سازی تصاویر و Media Handling

تصاویر بزرگ‌ترین عامل کندی سایت‌های وردپرسی هستند. در معماری Headless، این مشکل دوچندان می‌شود چون تصاویر از WordPress می‌آیند اما در Next.js رندر می‌شوند. خوشبختانه، کامپوننت next/image این مشکل را حل می‌کند:

import Image from 'next/image';

<Image
  src={post._embedded['wp:featuredmedia'][0].source_url}
  alt={post._embedded['wp:featuredmedia'][0].alt_text}
  width={800}
  height={600}
  sizes="(max-width: 768px) 100vw, 800px"
/>

کامپوننت next/image به‌طور خودکار: تصویر را در فرمت‌های مدرن (WebP، AVIF) سرو می‌کند، اندازه‌های Responsive تولید می‌کند، Lazy Loading را اعمال می‌کند، و از Layout Shift جلوگیری می‌نماید. برای اینکه این کامپوننت با تصاویر WordPress کار کند، باید دامنه WordPress در next.config.js تعریف شود:

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cms.example.com',
        pathname: '/wp-content/uploads/**',
      },
    ],
  },
};

اگر با بهترین فرمت تصویر برای وب آشنا شده باشید، می‌دانید که WebP و AVIF تفاوت محسوسی در حجم و کیفیت ایجاد می‌کنند. اگر با روش‌های بهبود Core Web Vitals آشنا شده باشید، می‌دانید که بهینه‌سازی تصاویر مستقیماً بر LCP اثر می‌گذارد.

SEO در معماری Headless

یکی از نگرانی‌های رایج در مهاجرت به Headless، حفظ SEO است. خوشبختانه، Next.js ابزارهای قدرتمندی برای SEO فراهم می‌کند. در App Router، از Metadata API استفاده می‌شود:

// app/posts/[slug]/page.tsx
import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPostBySlug(params.slug);
  return {
    title: post.yoast_head_json?.title || post.title.rendered,
    description: post.yoast_head_json?.description || post.excerpt.rendered,
    openGraph: {
      title: post.title.rendered,
      images: [post._embedded['wp:featuredmedia'][0].source_url],
    },
    alternates: {
      canonical: `https://example.com/posts/${params.slug}`,
    },
  };
}

نکته مهم: اگر از Yoast SEO یا Rank Math در WordPress استفاده می‌کنید، می‌توانید متادیتای آن‌ها را از REST API دریافت کنید. Yoast فیلد yoast_head_json را در پاسخ REST اضافه می‌کند که شامل تمام تگ‌های Meta است. این یعنی می‌توانید همان تنظیمات SEO تیم محتوا را در Next.js اعمال کنید.

سه عنصر حیاتی SEO در معماری Headless:

  • SSR/SSG: موتورهای جستجو باید HTML کامل را دریافت کنند. Next.js در حالت SSG و ISR این را تضمین می‌کند.
  • Structured Data: Schema.org باید در HTML نهایی وجود داشته باشد. از کامپوننت <script type="application/ld+json"> استفاده کنید.
  • Sitemap: یک Sitemap داینامیک با app/sitemap.ts بسازید که URLها را از WordPress دریافت کند.

اگر با سئو تکنیکال و اهمیت آن آشنا شده باشید، این سه عنصر را به‌عنوان پایه SEO فنی می‌شناسید.

استقرار و CDN

استقرار Next.js روی Vercel ساده‌ترین گزینه است: اتصال مخزن Git، تنظیم متغیرهای محیطی، و Deploy. Vercel به‌طور خودکار Build می‌کند، فایل‌ها را روی Edge Network توزیع می‌کند، و ISR را مدیریت می‌نماید.

گزینه‌های دیگر استقرار:

  • Netlify: با پشتیبانی از Next.js Runtime و Edge Functions
  • Cloudflare Pages: با Cloudflare Workers و R2 برای Asset Hosting
  • AWS Amplify: یکپارچگی با سرویس‌های AWS
  • Self-hosted: با Docker و Nginx (نیازمند پیکربندی دستی ISR)

برای WordPress، توصیه می‌شود که روی یک سرور مجزا یا یک سرویس Managed WordPress (مثل Kinsta یا WP Engine) میزبانی شود. این جداسازی، امنیت و مقیاس‌پذیری را افزایش می‌دهد. اگر با مفاهیم سرور و نحوه کار آن آشنا شده باشید، این معماری را به‌عنوان یک الگوی جداسازی لایه‌ها می‌شناسید.

اشتباهات رایج در اتصال وردپرس به Next.js

اشتباه اول: نادیده گرفتن CORS. اگر WordPress روی دامنه‌ای جداگانه باشد (مثل cms.example.com و www.example.com)، باید CORS را تنظیم کنید. بدون این تنظیم، درخواست‌های Client-Side Block می‌شوند:

// functions.php در WordPress
add_action( 'rest_api_init', function() {
    remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
    add_filter( 'rest_pre_serve_request', function( $value ) {
        header( 'Access-Control-Allow-Origin: https://www.example.com' );
        header( 'Access-Control-Allow-Methods: GET, POST, OPTIONS' );
        header( 'Access-Control-Allow-Headers: Content-Type, Authorization' );
        return $value;
    }, 15 );
} );

اشتباه دوم: Fetch کردن در Client Component بدون نیاز. اگر داده‌ای در سرور قابل دریافت است، در Client Component دریافت نکنید. این کار باعث افزایش Bundle Size و کاهش سرعت می‌شود.

اشتباه سوم: استفاده از useEffect برای داده‌کشی اولیه. در App Router، داده‌کشی باید در Server Component انجام شود. useEffect فقط برای داده‌کشی پس از تعامل کاربر مناسب است.

اشتباه چهارم: نادیده گرفتن Timeout. اگر WordPress کند باشد، Next.js باید پس از مدت مشخصی درخواست را لغو کند. از AbortSignal.timeout() استفاده کنید:

const res = await fetch(url, {
  signal: AbortSignal.timeout(10000),
  next: { revalidate: 60 },
});

اشتباه پنجم: عدم مدیریت خطای WordPress. اگر WordPress در دسترس نباشد، سایت Next.js باید یک Fallback نمایش دهد، نه یک صفحه خطای عمومی:

// app/error.tsx
'use client';

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>مشکلی در بارگذاری محتوا رخ داد</h2>
      <button onClick={() => reset()}>تلاش مجدد</button>
    </div>
  );
}

اشتباه ششم: عدم بهینه‌سازی WordPress برای Headless. اگر WordPress همچنان قالب‌های سنگین و افزونه‌های غیرضروری داشته باشد، REST API کند می‌شود. WordPress را به یک API Server سبک تبدیل کنید: قالب را به یک قالب Minimal تغییر دهید، افزونه‌های غیرضروری را غیرفعال کنید، و Object Cache (Redis یا Memcached) را فعال نمایید.

اگر با اشتباهات رایج در REST API و روش‌های جلوگیری آشنا شده باشید، این موارد را به‌عنوان بخشی از یک استراتژی جامع می‌شناسید.

پرسش‌های پرتکرار درباره اتصال وردپرس به Next.js

چگونه وردپرس را به Next.js متصل کنم؟

سه گام اصلی: اول، WordPress را روی یک دامنه جداگانه (مثل cms.example.com) راه‌اندازی کنید و REST API یا WPGraphQL را فعال نمایید. دوم، یک پروژه Next.js با App Router بسازید و متغیر محیطی WORDPRESS_API_URL را تنظیم کنید. سوم، در Server Components داده‌ها را با fetch یا Apollo Client دریافت کرده و رندر کنید. برای به‌روزرسانی خودکار محتوا، ISR یا On-Demand Revalidation را پیکربندی نمایید.

آیا Next.js برای سایت‌های وردپرسی معمولی مناسب است؟

برای سایت‌های کوچک و متوسط، معماری سنتی WordPress کافی است و مهاجرت به Next.js پیچیدگی بی‌مورد ایجاد می‌کند. Next.js زمانی ارزش دارد که: ترافیک بالا دارید، نیاز به SSR/SSG پیشرفته دارید، تیم فرانت‌اند جداگانه دارید، یا می‌خواهید از یک فریم‌ورک مدرن React استفاده کنید.

تفاوت ISR و SSR در Next.js چیست؟

SSR (Server-Side Rendering) صفحه را در هر درخواست رندر می‌کند و مناسب محتوای شخصی‌سازی‌شده است. ISR (Incremental Static Regeneration) صفحه را یک‌بار در Build می‌سازد و سپس در فواصل مشخصی بازتولید می‌کند. ISR سریع‌تر است چون پاسخ از Cache می‌آید، اما محتوا ممکن است تا چند دقیقه قدیمی باشد. برای سایت‌های محتوایی، ISR معمولاً بهترین تعادل را ایجاد می‌کند.

چگونه Preview Mode را در Next.js با WordPress پیاده‌سازی کنم؟

WordPress از Draft Preview پشتیبانی می‌کند. یک Endpoint در Next.js بسازید که با دریافت یک Secret معتبر، draftMode().enable() را فعال کند و به صفحه موردنظر Redirect کند. سپس در Loader، اگر Draft Mode فعال باشد، داده‌های پیش‌نویس را از REST API با یک Token احراز هویت دریافت کنید.

آیا اتصال وردپرس به Next.js بر SEO تأثیر منفی می‌گذارد؟

خیر، اگر به‌درستی پیاده‌سازی شود، SEO بهبود می‌یابد. Next.js با SSG و ISR HTML کامل را به موتورهای جستجو تحویل می‌دهد، TTFB را کاهش می‌دهد، و Core Web Vitals را بهبود می‌بخشد. نکته کلیدی، انتقال صحیح متادیتای SEO از WordPress (Yoast یا Rank Math) به Next.js است.

چگونه تصاویر WordPress را در Next.js بهینه کنم؟

از کامپوننت next/image استفاده کنید و دامنه WordPress را در next.config.js تعریف نمایید. Next.js به‌طور خودکار تصاویر را در فرمت‌های WebP و AVIF سرو می‌کند، Lazy Loading را اعمال می‌کند، و از Layout Shift جلوگیری می‌نماید. برای تصاویر موجود در WordPress، از پلاگین‌های بهینه‌سازی مثل Imagify یا ShortPixel نیز می‌توانید استفاده کنید.

آیا Next.js با WooCommerce کار می‌کند؟

بله. WooCommerce REST API و WPGraphQL for WooCommerce هر دو قابل استفاده در Next.js هستند. برای سبد خرید و پرداخت، از Server Actions یا Route Handlers استفاده کنید. برای مدیریت Session کاربر، JWT یا Cookie-based Session را پیاده‌سازی نمایید.

چگونه از WordPress در Next.js برای داده‌های پویا استفاده کنم؟

از استراتژی cache: 'no-store' یا next: { revalidate: 0 } برای داده‌های پویا استفاده کنید. برای داده‌های نیمه‌پویا، revalidate با مقدار مناسب (۶۰ یا ۳۰۰ ثانیه) را تنظیم کنید. برای به‌روزرسانی فوری، On-Demand Revalidation را با Webhook از WordPress پیاده‌سازی نمایید.

نگاه نهایی به معماری Headless با Next.js

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

سه معیار کلیدی برای تصمیم‌گیری:

۱. مقیاس و ترافیک. اگر سایت شما ترافیک بالایی دارد یا نیاز به SSR/SSG پیشرفته دارد، Next.js ارزش بررسی دارد. اگر سایت کوچکی دارید، معماری سنتی WordPress ساده‌تر و ارزان‌تر است.

۲. تیم و مهارت. اگر تیم شما با React و Next.js آشناست، مهاجرت روان‌تر است. اگر تیم شما فقط با PHP و WordPress کار کرده، هزینه یادگیری قابل توجه است.

۳. الزامات تجربه کاربری. اگر نیاز به تعامل بالا، Transition نرم، یا SPA-like Experience دارید، Next.js انتخاب برتر است. اگر سایت محتوایی ساده است، WordPress سنتی کافی است.

برای پروژه‌های جدید، توصیه می‌شود از همان ابتدا با App Router و Server Components شروع کنید تا از مزایای RSC بهره‌مند شوید. برای پروژه‌های موجود، مهاجرت تدریجی به Next.js امکان‌پذیر است، اما نیازمند برنامه‌ریزی دقیق است. اگر با اتصال وردپرس به Astro آشنا شده باشید، می‌دانید که Astro برای سایت‌های محتوایی ساده‌تر و سبک‌تر است، در حالی که Next.js برای اپلیکیشن‌های پیچیده‌تر مناسب است.

تحلیل سطح معماری

از منظر معماری نرم‌افزار، ترکیب Next.js و WordPress یک نمونه از Decoupled Architecture است که در آن، لایه نمایش از لایه داده جدا می‌شود. این جداسازی، یک Contract (قرارداد) بین دو سیستم ایجاد می‌کند: WordPress متعهد می‌شود که داده را در قالب REST یا GraphQL ارائه دهد و Next.js متعهد می‌شود که آن را به تجربه کاربری تبدیل کند. چالش اصلی، Sync State بین دو سیستم است: وقتی محتوا در WordPress تغییر می‌کند، Next.js چگونه مطلع می‌شود؟ سه راه‌حل استاندارد وجود دارد: زمان‌محور (ISR با revalidate)، رویدادمحور (Webhook-based Revalidation)، و درخواست‌محور (SSR با no-store). انتخاب بین این سه، تعادل بین تازگی محتوا و عملکرد را تعیین می‌کند. چالش دوم، Distributed Caching است: داده‌ها در چند لایه کش می‌شوند (Next.js Data Cache، CDN، Object Cache وردپرس) و Invalidations باید در تمام لایه‌ها همگام شوند. اگر با بهینه‌سازی پیشرفته دیتابیس وردپرس آشنا شده باشید، می‌دانید که این لایه‌بندی، کلید مقیاس‌پذیری در سیستم‌های توزیع‌شده است. چالش سوم، Type Safety است: داده‌هایی که از WordPress می‌آیند، ساختار مشخصی دارند اما TypeScript آن‌ها را نمی‌شناسد. راه‌حل، تولید Type از Schema (با GraphQL Code Generator) یا تعریف دستی Interfaceهاست. اگر با دلایل فنی بهبود کیفیت کد با TypeScript آشنا شده باشید، این رویکرد را به‌عنوان یک سرمایه‌گذاری بلندمدت می‌شناسید.

در مقیاس بسیار بالا — مثلاً یک پلتفرم با میلیون‌ها بازدید روزانه — معماری به سمت Edge Rendering و Streaming SSR حرکت می‌کند. Next.js روی Vercel Edge Functions اجرا می‌شود و صفحات را در نزدیک‌ترین نقطه به کاربر رندر می‌کند. Server Components اجازه می‌دهند بخش‌های مختلف صفحه به‌صورت موازی و تدریجی رندر شوند. این معماری، ترکیبی از بهترین‌های هر دو دنیاست: سرعت CDN با انعطاف‌پذیری SSR. اگر با طراحی معماری وب مقیاس‌پذیر آشنا شده باشید، این الگو را به‌عنوان تکامل طبیعی معماری‌های Headless می‌شناسید. تیم‌هایی که این سطح از معماری را درک می‌کنند، می‌توانند سیستم‌هایی بسازند که هم در مقیاس کوچک و هم در مقیاس میلیونی کار می‌کنند.

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

همچنین اگر می‌خواهید در مورد پیاده‌سازی عملی Next.js و WordPress بیشتر بدانید، مفاهیم پایه REST API و بهینه‌سازی طراحی وب برای سئو می‌توانند نقاط شروع خوبی باشند.