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

نشر موقع Nuxt على Cloudflare Pages (وتجنّب الأخطاء الشائعة)

نشر في 26 Sep 2026· 5 min قراءة
#Nuxt#Cloudflare#DevOps#CI/CD

موقع شخصي يُقدَّم من شبكة Cloudflare

هذا الموقع تطبيق Nuxt 3 تُولَّد جميع صفحاته مسبقاً أثناء البناء: الصفحة الرئيسية وصفحات السيرة الذاتية وكل مقالات المدونة. وCloudflare Pages استضافة مثالية لهذه الحالة: صفحات HTML تُقدَّم من شبكة Cloudflare العالمية، وHTTPS تلقائي، ونشر مع كل عملية push، ومعاينة لكل فرع. إليك الإعداد، والأهم من ذلك الأخطاء الثلاثة التي واجهتها أثناء إعادة التصميم الأخيرة.

إعدادات البناء

في لوحة التحكم (Workers & Pages ← مشروعك ← الإعدادات ← البناء):

  • أمر البناء: npm run build
  • مجلد المخرجات: dist
  • فرع الإنتاج: master (أو main)

يكتشف Nuxt بيئة Cloudflare Pages تلقائياً ويستخدم إعداد Nitro المسبق cloudflare-pages: تصبح المسارات المولَّدة مسبقاً ملفات HTML ثابتة في dist/، ويخدم Worker كل ما عداها. ولموقع ثابت بالكامل، صرّح بالمسارات المطلوب توليدها في nuxt.config.ts. وتوليدها من بياناتك يضمن ألّا تنسى أي مقال:

import { blogArticles } from './data/blog'

const staticPages = ['/', '/experience', '/skills', '/projects', '/education', '/blog']
const blogPages = blogArticles.map(article => `/blog/${article.slug}`)

export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: [...staticPages, ...blogPages],
      crawlLinks: true,
    },
  },
})

المصفوفة نفسها تغذّي خريطة الموقع (sitemap): أي مقال جديد يُولَّد ويُفهرس تلقائياً دون تعديل أي شيء آخر.

الفخ الأول: فرع الإنتاج

بعد دفع التصميم الجديد إلى master لم يتغير الموقع المنشور، مع أن البناء نجح. السبب أن فرع الإنتاج في المشروع كان ما يزال مضبوطاً على فرع عمل قديم، فكانت كل عملية push إلى master تنتج نشر معاينة فقط على رابط *.pages.dev دون المساس بالنطاق الرئيسي.

تحقق من ذلك في الإعدادات ← البناء ← التحكم في الفروع. وتغيير فرع الإنتاج لا يعيد النشر وحده: تحتاج إلى commit جديد على ذلك الفرع (أو إعادة تشغيل عملية نشر) لتحديث بيئة الإنتاج.

الفخ الثاني: إصدار Node

يتطلب Nuxt 3.21 وVite 7 وNitro الإصدار Node ^20.19 أو >=22.12. يقرأ نظام البناء في Cloudflare الإصدار من ملف .node-version أو .nvmrc في جذر المستودع (أو من متغير البيئة NODE_VERSION). القيمة 20 وحدها غامضة: ثبّت إصداراً رئيسياً حديثاً متوافقاً بوضوح.

echo 22 > .node-version
echo 22 > .nvmrc

الفخ الثالث: ملف القفل وnpm ci

كان البناء يفشل خلال ثوانٍ بهذه الرسالة:

npm error `npm ci` can only install packages when your package.json and
package-lock.json or npm-shrinkwrap.json are in sync.
npm error Missing: oxc-parser@0.151.0 from lock file
npm error Missing: esbuild@0.28.2 from lock file
...

ومع ذلك كان npm install والبناء يعملان محلياً دون أي مشكلة. السبب أن الملف package-lock.json وُلِّد باستخدام npm 11 (المرفق مع Node 24)، بينما تثبّت Cloudflare الاعتماديات بالأمر npm ci على npm 10. لا يحلّ الإصداران الاعتماديات الاختيارية بالطريقة نفسها، فاعتبر npm 10 ملف القفل غير متزامن.

الحل: إعادة توليد ملف القفل بإصدار npm نفسه المستخدم في بيئة CI، والمصرَّح به في الحقل packageManager من ملف package.json:

npx npm@10.9.4 install --package-lock-only

والأهم: أعد إنتاج بيئة CI محلياً قبل الدفع، على نسخة نظيفة من المستودع:

git clone . /tmp/ci-check && cd /tmp/ci-check
npx npm@10.9.4 ci
npm run build

إذا نجح هذان الأمران فسينجح البناء على Cloudflare أيضاً.

إعادة التوجيه إلى الشرطة المائلة الختامية

بعد النشر، يُرجع الأمر curl -I https://benmacha.tn/experience الرمز 308 نحو /experience/. هذا ليس خطأ: كل صفحة مولَّدة مسبقاً هي ملف experience/index.html، وتعيد Cloudflare Pages التوجيه إلى رابط المجلد. ولتحسين محركات البحث، اجعل الروابط الداخلية والروابط القانونية (canonical) متسقة مع هذا السلوك لتجنّب إعادة توجيه عند كل نقرة.

متابعة النشر دون فتح لوحة التحكم

تنشر Cloudflare حالة كل عملية بناء على GitHub على شكل check run مرتبط بالـ commit. وباستخدام أداة GitHub CLI يمكنك متابعة النشر من الطرفية:

gh api repos/MOI/MON-REPO/commits/$(git rev-parse HEAD)/check-runs \
  --jq '.check_runs[] | select(.name=="Cloudflare Pages") | "\(.status) \(.conclusion)"'

تنتقل النتيجة من in_progress إلى completed success أو completed failure، وفي الحالة الأخيرة يقودك الرابط details_url مباشرة إلى سجلات البناء.

باختصار

  • تأكد أن فرع الإنتاج هو الفرع الذي تدفع إليه
  • ثبّت إصدار Node في .node-version بما يتوافق مع اعتمادياتك
  • ولّد ملف القفل بإصدار npm نفسه المستخدم في CI، واختبر npm ci محلياً
  • ولّد المسارات المسبقة وخريطة الموقع من بياناتك

بعد ضبط هذه النقاط تصبح دورة العمل مثالية: git push واحد، ودقيقة من البناء، ويصبح الموقع محدَّثاً في كل أنحاء العالم.