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 getStaticProps() {
  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يحتوي على اللغة الافتراضية المكونة (إذا تم تمكينها).
revalidateReasonيوفر سببًا لاستدعاء الدالة. يمكن أن يكون أحد: "build" (يعمل أثناء البناء)، "stale" (انتهت فترة إعادة التحقق، أو يعمل في وضع التطوير)، "on-demand" (تم تشغيله عبر إعادة التحقق عند الطلب)

قيم إرجاع getStaticProps

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

props

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

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

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 }, // سيتم تمريرها إلى مكون الصفحة كـ props
  }
}

جيد للمعرفة: 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 }, // سيتم تمريرها إلى مكون الصفحة كـ props
  }
}

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

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

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

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

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

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

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

// سيتم ملء posts أثناء البناء بواسطة 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` كـ prop أثناء البناء
  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.