getStaticProps

تصدير دالة تسمى getStaticProps سيقوم بعرض الصفحة مسبقًا أثناء البناء باستخدام الخصائص (props) التي تُرجعها الدالة:

import type { InferGetStaticPropsType, GetStaticProps } from 'next'

type Repo = {
  name: string
  stargazers_count: number
}

export const getStaticProps = (async (context) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}) satisfies GetStaticProps<{
  repo: Repo
}>

export default function Page({
  repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
  return repo.stargazers_count
}
export async function getStaticPaths() {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}

export default function Page({ repo }) {
  return repo.stargazers_count
}

يمكنك استيراد الوحدات (modules) في النطاق العلوي لاستخدامها في getStaticProps. الوحدات المستوردة لن يتم تضمينها لجانب العميل. هذا يعني أنه يمكنك كتابة كود خاص بالخادم مباشرة في getStaticProps، بما في ذلك جلب البيانات من قاعدة البيانات الخاصة بك.

معامل Context

معامل context هو كائن يحتوي على المفاتيح التالية:

الاسمالوصف
paramsيحتوي على معلمات المسار للصفحات التي تستخدم المسارات الديناميكية. على سبيل المثال، إذا كان اسم الصفحة هو [id].js، فإن params سيبدو مثل { id: ... }. يجب استخدام هذا مع getStaticPaths، والذي سنشرحه لاحقًا.
preview(مهمل لصالح draftMode) preview يكون true إذا كانت الصفحة في وضع المعاينة و false بخلاف ذلك.
previewData(مهمل لصالح draftMode) بيانات المعاينة المعينة بواسطة setPreviewData.
draftModedraftMode يكون true إذا كانت الصفحة في وضع المسودة و false بخلاف ذلك.
localeيحتوي على اللغة النشطة (إذا كانت ممكّنة).
localesيحتوي على جميع اللغات المدعومة (إذا كانت ممكّنة).
defaultLocaleيحتوي على اللغة الافتراضية المكونة (إذا كانت ممكّنة).

قيم إرجاع getStaticProps

يجب أن تُرجع دالة getStaticProps كائنًا يحتوي إما على props، أو redirect، أو notFound متبوعًا بخاصية اختيارية revalidate.

props

كائن props هو زوج مفتاح-قيمة، حيث يتم استقبال كل قيمة بواسطة مكون الصفحة. يجب أن يكون كائنًا قابلاً للتسلسل بحيث يمكن تسلسل أي خصائص يتم تمريرها باستخدام JSON.stringify.

export async function getStaticProps(context) {
  return {
    props: { message: `Next.js is awesome` }, // سيتم تمريرها إلى مكون الصفحة كخصائص
  }
}

revalidate

خاصية revalidate هي المقدار بالثواني الذي بعدها يمكن أن يحدث إعادة إنشاء للصفحة (القيمة الافتراضية هي false أو بدون إعادة تحقق).

// يتم استدعاء هذه الدالة أثناء البناء على جانب الخادم.
// قد يتم استدعاؤها مرة أخرى، على دالة بدون خادم، إذا
// تم تمكين إعادة التحقق وجاء طلب جديد
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // ستحاول Next.js إعادة إنشاء الصفحة:
    // - عند وصول طلب
    // - على الأكثر مرة كل 10 ثواني
    revalidate: 10, // بالثواني
  }
}

تعلم المزيد عن التجديد الثابت التدريجي.

يمكن تحديد حالة التخزين المؤقت لصفحة تستخدم ISR عن طريق قراءة قيمة رأس الاستجابة x-nextjs-cache. القيم الممكنة هي التالية:

  • MISS - المسار غير موجود في التخزين المؤقت (يحدث مرة واحدة على الأكثر، في الزيارة الأولى)
  • STALE - المسار موجود في التخزين المؤقت ولكنه تجاوز وقت إعادة التحقق لذا سيتم تحديثه في الخلفية
  • HIT - المسار موجود في التخزين المؤقت ولم يتجاوز وقت إعادة التحقق

notFound

القيمة المنطقية notFound تسمح للصفحة بإرجاع حالة 404 وصفحة 404. مع notFound: true، سترجع الصفحة 404 حتى لو كانت هناك صفحة تم إنشاؤها بنجاح من قبل. هذا مخصص لدعم حالات الاستخدام مثل المحتوى الذي ينشئه المستخدم ويتم إزالته بواسطة مؤلفه. لاحظ أن notFound يتبع نفس سلوك revalidate الموضح هنا.

export async function getStaticProps(context) {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  if (!data) {
    return {
      notFound: true,
    }
  }

  return {
    props: { data }, // سيتم تمريرها إلى مكون الصفحة كخصائص
  }
}

معلومة جيدة: notFound غير مطلوب لوضع fallback: false حيث سيتم فقط عرض المسارات التي تم إرجاعها من getStaticPaths مسبقًا.

redirect

كائن redirect يسمح بإعادة التوجيه إلى موارد داخلية أو خارجية. يجب أن يتطابق مع الشكل { destination: string, permanent: boolean }.

في بعض الحالات النادرة، قد تحتاج إلى تعيين رمز حالة مخصص لعملاء HTTP القديمة لإعادة التوجيه بشكل صحيح. في هذه الحالات، يمكنك استخدام خاصية statusCode بدلاً من خاصية permanent، ولكن ليس كلاهما. يمكنك أيضًا تعيين basePath: false مشابهًا لإعادة التوجيه في next.config.js.

export async function getStaticProps(context) {
  const res = await fetch(`https://...`)
  const data = await res.json()

  if (!data) {
    return {
      redirect: {
        destination: '/',
        permanent: false,
        // statusCode: 301
      },
    }
  }

  return {
    props: { data }, // سيتم تمريرها إلى مكون الصفحة كخصائص
  }
}

إذا كانت عمليات إعادة التوجيه معروفة في وقت البناء، فيجب إضافتها في next.config.js بدلاً من ذلك.

قراءة الملفات: استخدم process.cwd()

يمكن قراءة الملفات مباشرة من نظام الملفات في getStaticProps.

للقيام بذلك، يجب الحصول على المسار الكامل للملف.

بما أن Next.js يقوم بتجميع الكود الخاص بك في دليل منفصل، لا يمكنك استخدام __dirname لأن المسار الذي سيعود به سيكون مختلفًا عن مسار الصفحة.

بدلاً من ذلك، يمكنك استخدام process.cwd() الذي يعطيك الدليل الذي يتم فيه تنفيذ Next.js.

import { promises as fs } from 'fs'
import path from 'path'

// سيتم ملء المنشورات أثناء البناء بواسطة getStaticProps()
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>
          <h3>{post.filename}</h3>
          <p>{post.content}</p>
        </li>
      ))}
    </ul>
  )
}

// يتم استدعاء هذه الدالة أثناء البناء على جانب الخادم.
// لن يتم استدعاؤها على جانب العميل، لذا يمكنك حتى إجراء
// استعلامات قاعدة بيانات مباشرة.
export async function getStaticProps() {
  const postsDirectory = path.join(process.cwd(), 'posts')
  const filenames = await fs.readdir(postsDirectory)

  const posts = filenames.map(async (filename) => {
    const filePath = path.join(postsDirectory, filename)
    const fileContents = await fs.readFile(filePath, 'utf8')

    // بشكل عام، ستحلل/تحول المحتويات
    // على سبيل المثال، يمكنك تحويل Markdown إلى HTML هنا

    return {
      filename,
      content: fileContents,
    }
  })
  // بإرجاع { props: { posts } }، سيستقبل مكون Blog
  // `posts` كخاصية أثناء البناء
  return {
    props: {
      posts: await Promise.all(posts),
    },
  }
}

export default Blog

سجل الإصدارات

الإصدارالتغييرات
v13.4.0موجه التطبيق أصبح الآن مستقرًا مع جلب بيانات مبسط
v12.2.0التجديد الثابت التدريجي عند الطلب أصبح مستقرًا.
v12.1.0تمت إضافة التجديد الثابت التدريجي عند الطلب (بيتا).
v10.0.0تمت إضافة خيارات locale، locales، defaultLocale، و notFound.
v10.0.0تمت إضافة خيار الإرجاع fallback: 'blocking'.
v9.5.0أصبح التجديد الثابت التدريجي مستقرًا.
v9.3.0تم تقديم getStaticProps.