العودة إلى المدونة

التصدير الثابت في Next.js ‏(output: 'export'): الدليل الكامل

التصدير الثابت في Next.js ‏(output: 'export'): الدليل الكامل

10 أكتوبر 2026 — Next.js

تاريخ النشر

10 أكتوبر 2026

مدة القراءة

3 دقيقة للقراءة

التصنيف

Next.js

الوسوم

  • Next.js
  • Static Export
  • App Router
  • Hosting

(مقدمة)كيف يعمل التصدير الثابت في Next.js مع App Router، وما لا يستطيع فعله، والحلول البديلة للصور والمسارات الديناميكية والنماذج وإعادة التوجيه.

موقع Next.js المُصدَّر بشكل ثابت ليس سوى ملفات HTML وCSS وJavaScript وموارد في مجلد. يمكنك وضع هذا المجلد على أي مستضيف للمواقع الثابتة (Cloudflare Pages أو GitHub Pages أو S3 أو Netlify أو خادم Nginx) دون خادم Node.js تحتاج إلى تشغيله أو تحديثه أو الدفع مقابله. وهذا الموقع مبني بهذه الطريقة تمامًا.

يشرح هذا الدليل كيف يعمل التصدير الثابت في App Router، وما الذي تتخلى عنه، وكيف تتجاوز كل قيد.

تفعيله

منذ Next.js 14 لم يعد next export موجودًا؛ أصبح التصدير الثابت خيارًا في الإعدادات:

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  // Optional: /about → /about/index.html instead of /about.html
  trailingSlash: true,
  images: { unoptimized: true },
}

export default nextConfig

يكتب next build الموقع الآن في out/. عاينه بأي خادم ملفات ثابتة:

bash
npx serve out

ما الذي يعمل

أكثر مما يتوقعه الناس:

  • مكونات الخادم. تعمل مرة واحدة أثناء البناء. اجلب البيانات، واقرأ الملفات، واستدعِ الواجهات البرمجية؛ وستُثبَّت النتيجة في HTML.
  • مكونات العميل والخطافات والسياق (Context) وكل مكتبات المتصفح.
  • المسارات الديناميكية، ما دمت تسرد كل مسار عبر generateStaticParams.
  • معالجات المسارات (Route Handlers) بطريقة GET، وتتحول إلى ملفات ثابتة (مفيدة لـ feed.json وsitemap.xml وrobots.txt).
  • واجهة Metadata: العناوين والأوصاف وOpen Graph والروابط الأساسية.
  • التنقل في المتصفح باستخدام <Link> مع التحميل المسبق.

ما الذي لا يعمل، وما البديل

الميزة سبب فشلها الحل البديل
تحسين الصور الافتراضي يحتاج إلى خادم images.unoptimized: true، أو صور مُعدّة الحجم مسبقًا، أو محمّل مخصص (Cloudinary أو imgix أو Cloudflare Images)
مسارات ديناميكية دون generateStaticParams يجب أن تُعرف الصفحات أثناء البناء اسرد كل المعاملات، واضبط dynamicParams = false
cookies() وheaders() وبيانات وقت الطلب لا يوجد طلب أثناء التشغيل اقرأها في المتصفح، أو انقل المنطق إلى واجهة برمجية
Server Actions تحتاج إلى خادم أرسل POST إلى دالة بلا خادم (Workers أو Lambda)
Middleware يحتاج إلى خادم قواعد لدى المستضيف: _redirects و_headers ودوال الحافة
redirects وrewrites وheaders في الإعدادات يطبّقها خادم Next كذلك: اضبطها لدى المستضيف
ISR / ‏revalidate لا خادم لإعادة التوليد أعد البناء عند تغيّر المحتوى (دفع إلى Git أو webhook)
توجيه i18n المدمج ميزة في Pages Router مقاطع اللغة: app/[lang]/... مع generateStaticParams

المسارات الديناميكية كما يجب

كل مقطع ديناميكي يحتاج إلى قائمة بقيمه أثناء البناء:

app/blog/[slug]/page.tsx
import { getAllPosts, getPost } from '@/lib/blog'
import { notFound } from 'next/navigation'

export const dynamicParams = false // unknown slugs are a 404, not a runtime render

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

export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  const post = await getPost(slug)
  if (!post) notFound()
  return <article dangerouslySetInnerHTML={{ __html: post.html }} />
}

لاحظ أن params في Next.js 15 وعدٌ (Promise)، فاستخدم معه await.

فخ واحد: إذا أعاد generateStaticParams مصفوفة فارغة، يفشل البناء لأن المسار لن ينتج أي صفحات. وإن كانت المجموعة قد تكون فارغة (مدونة جديدة مثلًا)، فأعد معاملًا مؤقتًا واتركه يعرض صفحة 404.

الصور

لديك ثلاثة خيارات معقولة:

  1. unoptimized: true مع تصدير الصور بنفسك بالحجم المناسب (WebP أو AVIF، بعرض يعادل مرة أو مرتين عرض العرض الفعلي). بسيط وسريع إن كنت منضبطًا.
  2. محمّل مخصص يشير إلى شبكة توصيل للصور، تعيد نسخًا بأحجام مختلفة عند الطلب:
image-loader.js
export default function loader({ src, width, quality }) {
  return `https://images.example.com/${src}?w=${width}&q=${quality || 75}`
}
next.config.mjs
const nextConfig = {
  output: 'export',
  images: { loader: 'custom', loaderFile: './image-loader.js' },
}
  1. وسم <img> عادي مع srcset وloading="lazy" وwidth/height صريحة لتجنّب إزاحة التخطيط.

النماذج وكل ما يجري على الخادم

يمكن للموقع الثابت أن يحتوي على نماذج وبحث وتسجيل دخول؛ كل ما في الأمر أن جزء الخادم يعيش في مكان آخر. والنمط المعتاد دالة صغيرة بلا خادم تستدعيها الصفحة عبر fetch. وقد شرحتُ الدالة التي يستخدمها هذا الموقع في نموذج تواصل بلا خوادم باستخدام Cloudflare Workers وD1.

إعادة التوجيه والترويسات

اضبطها لدى المستضيف. في Cloudflare Pages وNetlify، يُنسخ ملف _redirects الموجود في public/ إلى out/:

public/_redirects
/old-page    /new-page    301
/blog/*      /journal/:splat    301

وملف _headers لترويسات التخزين المؤقت والأمان:

public/_headers
/_next/static/*
  Cache-Control: public, max-age=31536000, immutable

تحديث المحتوى دون خادم

لأنه لا يوجد ISR، يحتاج كل تغيير في المحتوى إلى إعادة بناء. يبدو هذا أسوأ مما هو عليه: اربط المستضيف بمستودع Git، وسيُبنى الموقع ويُنشر مع كل دفع خلال دقيقة أو اثنتين. وللمحتوى الموجود في نظام إدارة محتوى، وجّه الـ webhook الخاص به إلى رابط النشر لدى المستضيف. أما للمدونة، فأبسط خيار على الإطلاق إبقاء المقالات بصيغة Markdown في المستودع؛ راجع مدونة Markdown في Next.js دون نظام إدارة محتوى.

متى يكون التصدير الثابت خيارًا خاطئًا

  • صفحات تعتمد على هوية المستخدم المسجّل وتُعرض على الخادم.
  • آلاف الصفحات التي تتغير كل بضع دقائق (يزداد وقت البناء بزيادة عدد الصفحات).
  • أي شيء يحتاج فعلًا إلى العرض وقت الطلب، مثل الأسعار المخصصة لكل مستخدم.

أما للمواقع التسويقية، ومعارض الأعمال، والتوثيق، والمدونات، وصفحات الهبوط، فالتصدير الثابت عادةً أسرع الخيارات وأرخصها وأكثرها متانة.

قائمة التحقق

  • ‏output: 'export' في next.config
  • لكل مسار ديناميكي generateStaticParams وdynamicParams = false
  • معالجة الصور (unoptimized، أو محمّل مخصص، أو <img>)
  • لا cookies() ولا headers() ولا Server Actions ولا Middleware
  • ضبط إعادة التوجيه والترويسات لدى المستضيف
  • تشغيل النشر عبر الدفع إلى Git أو webhooks نظام إدارة المحتوى
  • معاينة out/ محليًا قبل النشر الأول

الخطوة التالية: تأكّد أن محركات البحث تفهم الصفحات التي تصدّرها؛ راجع تحسين محركات البحث تقنيًا في Next.js App Router.

النشرة البريدية

تصلك المقالات الجديدة على بريدك

رسالة قصيرة عند نشر كل جديد. بلا رسائل مزعجة، ويمكنك إلغاء الاشتراك في أي وقت.

تحسين محركات البحث تقنيًا في Next.js App Router: قائمة عملية
تحسين محركات البحث تقنيًا في Next.js App Router: قائمة عملية
المقال التالي