كيف تصلح أخطاء 404 بعد النشر لموقعك أو تطبيقك
إذا كان تطبيقك يعمل محلياً لكن الصفحات تعطي 404 بعد النشر، فالسبب الأكثر شيوعاً هو غياب توجيه تطبيق الصفحة الواحدة (SPA): الخادم يبحث عن ملف اسمه /dashboard غير موجود، لأن هذا المسار موجود فقط داخل JavaScript. الحل قاعدة احتياطية تعيد index.html لمسارات التطبيق. الأسباب الأخرى تشمل ملفات مفقودة من مخرجات البناء، ومسارات حساسة لحالة الأحرف، والاختلاف في الشرطة المائلة في النهاية، ومسار أساسي (base path) خاطئ، وواجهات برمجية لم تُنشر أصلاً.
ابدأ بملاحظة الرابط الدقيق الذي يعطي 404، وكيف وصلت إليه. النمط يشير مباشرة إلى السبب.
الخطوة 1: حدّد النمط
| ما تراه | السبب الأرجح | انتقل إلى |
|---|---|---|
| الصفحة الرئيسية تعمل، والنقر على الروابط يعمل، لكن تحديث الصفحة أو فتح رابط مباشر يعطي 404 | لا توجد قاعدة احتياطية لـ SPA | الخطوة 2 |
| كل الصفحات تعطي 404، بما فيها الصفحة الرئيسية | نُشر المجلد الخطأ، أو لم يُنشر البناء | الخطوة 3 |
| الصفحات تُحمَّل، لكن الصور أو الخطوط أو السكربتات تعطي 404 | ملفات مفقودة من البناء، أو مسارات خاطئة | الخطوة 4 |
يعمل مع /about/ ويفشل مع /about (أو العكس) | التعامل مع الشرطة المائلة في النهاية | الخطوة 5 |
/About يفشل لكن /about يعمل | الخادم حساس لحالة الأحرف | الخطوة 4 |
الصفحة تُحمَّل، لكن طلبات البيانات إلى /api/... تعطي 404 | الواجهة البرمجية غير منشورة أو غير موجهة | الخطوة 6 |
| الروابط القديمة من موقع سابق تعطي 404 | إعادة توجيه مفقودة | الخطوة 7 |
| فقط على النطاق المخصص | إعداد DNS أو النطاق | الخطوة 8 |
لرؤية رمز الحالة الفعلي، افتح أدوات المطوّر (انقر بالزر الأيمن ← Inspect أو «فحص»)، واذهب إلى تبويب Network، وأعد التحميل، وانظر إلى حالة الطلب الأول.
الخطوة 2: أضف قاعدة الرجوع لـ SPA
هذه هي الحالة الكلاسيكية. في تطبيقات الصفحة الواحدة بـ React أو Vue أو Svelte، يملك الخادم عدداً محدوداً من الملفات الحقيقية: index.html وبعض ملفات JavaScript وCSS. المسارات مثل /dashboard أو /projects/42 يتولاها موجّه داخل المتصفح.
- النقر على رابط يعمل: يغيّر الموجّه الرابط ويرسم الصفحة الجديدة دون أن يسأل الخادم.
- تحديث الصفحة أو فتح رابط مباشرة يفشل: يطلب المتصفح من الخادم
/dashboard، ولا يوجد هذا الملف، فيعيد الخادم 404.
الحل قاعدة تقول: إذا لم يطابق الطلب ملفاً حقيقياً، فأعد index.html بحالة 200، ودع الموجّه يتولى الباقي. الطريقة تعتمد على المزود (تحقق من الوثائق الحالية لمزودك، فالتفاصيل تتغير):
| المزود | قاعدة الرجوع المعتادة |
|---|---|
| Netlify | ملف _redirects في المجلد المنشور يحوي /* /index.html 200 |
| Vercel | rewrite في vercel.json من كل المسارات إلى /index.html (إعدادات الأطر غالباً تتولى ذلك) |
| Cloudflare Pages | يقدم رجوعاً بنمط SPA افتراضياً إذا لم يوجد ملف 404.html في المستوى الأعلى |
| Nginx | try_files $uri $uri/ /index.html; داخل كتلة location / |
| Apache | قاعدة rewrite في .htaccess ترسل الطلبات غير الملفات إلى index.html |
| GitHub Pages | لا توجد إعادة كتابة من جهة الخادم؛ والحلول البديلة الشائعة هي التوجيه بالهاش، أو ملف 404.html يعيد التوجيه |
تأكد أن القاعدة لا تبتلع الملفات الحقيقية: طلبات مثل /assets/app.js يجب أن تعيد ملف JavaScript الفعلي. إذا أعادت index.html بدلاً منه، ستحصل على صفحة فارغة مع خطأ «Failed to load module script». راجع إصلاح الصفحة البيضاء الفارغة.
أعطِ الموجّه أيضاً مساراً شاملاً (catch-all) حتى تعرض الروابط التي لا تطابق أي صفحة رسالة «الصفحة غير موجودة» ودية، بدلاً من لا شيء.
إذا لم تستطع تغيير إعدادات الخادم، فإن التوجيه بالهاش (روابط مثل /#/dashboard) يتجنب المشكلة، لأن الجزء الذي يأتي بعد # لا يُرسل إلى الخادم أبداً. هذا حل بديل وليس الخيار الأول: الروابط أقل جمالاً وأقل ودية لمحركات البحث.
الأطر التي تُولّد الصفحات على الخادم أو وقت البناء (Next.js وAstro وما شابهها) تملك عادةً ملفات حقيقية أو مسارات خادم لكل صفحة، لذلك هذه المشكلة أقل شيوعاً فيها. ما يعادلها هناك هو صفحة لم تُولَّد وقت البناء.
الخطوة 3: تحقق مما نُشر فعلاً
إذا كانت كل الصفحات تعطي 404، فالأرجح أن الخادم لا يقدم تطبيقك المبني.
- المجلد الصحيح. يجب أن تنشر المنصة مخرجات البناء (عادةً
distلـ Vite، وbuildلـ Create React App، وoutلتصدير Next.js الثابت)، لا جذر المشروع. - البناء اكتمل. اقرأ سجل النشر. إذا فشل البناء، فقد لا تنشر المنصة شيئاً، أو تنشر نسخة قديمة.
- ملف
index.htmlفي المستوى الأعلى للمجلد المنشور، لا داخل مجلد فرعي. - المسار الأساسي متطابق. إذا كان التطبيق يُقدَّم من
example.com/app/، فيجب بناؤه بذلك المسار الأساسي (خيارbaseفي Vite، أوbasenameفي React Router)، وإلا ستخطئ كل المسارات والأصول.
الخطوة 4: أصلح الملفات المفقودة والمسارات الخاطئة
عندما تُحمَّل الصفحات لكن الأصول تعطي 404:
- حساسية حالة الأحرف. macOS وWindows يعاملان عادةً
Logo.pngوlogo.pngكالملف نفسه. معظم خوادم Linux لا تفعل. اجعل كل مرجع مطابقاً لاسم الملف الفعلي حرفاً بحرف. - ملفات خارج البناء. في Vite، الملفات الموجودة في
public/تُنسخ كما هي وتُشار إليها من الجذر (/logo.png). الملفات المستوردة في الكود تُحزَم ضمن البناء. ملف موجود في مكان آخر من المشروع قد لا يُنشر أصلاً. - المسارات النسبية.
images/photo.jpgيُحسب نسبةً إلى الرابط الحالي، لذا ينكسر على/blog/post-1. استخدم/images/photo.jpg. - ملفات مرفوعة محفوظة على القرص المحلي. إذا كُتبت ملفات المستخدمين المرفوعة إلى المجلد المحلي للخادم، فستختفي عند نشر نسخة جديدة. استخدم تخزين ملفات حقيقياً.
الخطوة 5: تعامل مع الشرطة المائلة في النهاية باتساق
/about و/about/ عنوانان مختلفان. تختلف المنصات في إضافة الشرطة المائلة أو حذفها، وعدم التطابق مع روابطك أو مع الموجّه قد يسبب 404 أو حلقات إعادة توجيه. اختر نمطاً واحداً، واجعل روابطك تستخدمه، واضبط المنصة لتعيد توجيه الشكل الآخر إليه. الاتساق يساعد محركات البحث أيضاً، التي قد ترى نسختين من كل صفحة.
الخطوة 6: أصلح واجهات البرمجة التي تعطي 404
إذا تُحمَّلت الصفحة لكن تبويب Network يُظهر طلبات /api/... تعيد 404:
- الخلفية غير منشورة. الاستضافة الثابتة تقدم الملفات فقط؛ يجب أن تعمل الخلفية في مكان ما.
- المسار موجَّه بشكل مختلف في الإنتاج. في التطوير، قد يحوّل وكيل (proxy) الطلبات من
/apiإلى خادم منفصل. في الإنتاج، تحتاج المنصة إلى إعادة توجيه مكافئة، أو يجب أن تستدعي الواجهة الأمامية العنوان الحقيقي للواجهة البرمجية. - قاعدة الرجوع التقطت الطلب. طلب الواجهة البرمجية الذي يعيد
index.htmlبحالة 200 يعني أن قاعدة الرجوع واسعة جداً. استثنِ/api/*منها.
طلبات التطبيق المنشور إلى /api/orders تعطي 404، رغم أنها تعمل في المعاينة. تحقق من طريقة توجيه /api في المعاينة مقابل التطبيق المنشور، واجعل الواجهة الأمامية المنشورة تصل إلى الخلفية بالطريقة نفسها.
الخطوة 7: أعد توجيه الروابط القديمة
إذا انتقلت من موقع آخر أو أعدت هيكلة موقعك، فالروابط القديمة التي ما زال الناس ومحركات البحث يستخدمونها ستعطي 404. أضف إعادة توجيه 301 (دائمة) من كل رابط قديم إلى موقعه الجديد. احتفظ بقائمة واختبر عيّنة منها بعد الإطلاق. ويشرح دليلنا عن نقل موقع WordPress كيفية بناء هذه القائمة.
الخطوة 8: تحقق من النطاق
إذا كان التطبيق يعمل على عنوان المزود لكنه يعطي 404 على نطاقك المخصص، فقد يشير النطاق إلى مشروع خاطئ، أو قد لا يكون المزود قد ربط النطاق بموقعك بعد. تحقق من سجلات DNS وإعدادات النطاق لدى المزود. راجع كيف تربط نطاقاً مخصصاً.
اجعل صفحة 404 الحقيقية مفيدة
بعض حالات 404 صحيحة: شخص كتب الرابط بشكل خاطئ. اجعل تلك الصفحة مفيدة:
- رسالة قصيرة، ورابط للصفحة الرئيسية والأقسام الأساسية
- مربع بحث، إذا كان في الموقع بحث
- الترويسة والتنقل نفسهما كبقية الموقع
حيثما يسمح إعدادك، أرجع حالة 404 حقيقية للصفحات غير الموجودة. رسالة «غير موجود» مع حالة 200 هي ما تسميه محركات البحث خطأً ناعماً (soft 404)، وقد يهدر وقت الزحف ويربك الفهرسة.
أخطاء شائعة
- الاختبار بالنقر فقط. اختبر دائماً بلصق الروابط العميقة في نافذة جديدة وتحديثها.
- قاعدة رجوع تلتقط كل شيء. الأصول وطلبات الواجهة البرمجية تعيد
index.html، فتنتج صفحات فارغة وأخطاء API مربكة. - اختلاف في حالة الأحرف لا يظهر إلا على الخادم.
- نشر مجلد المصدر بدلاً من مخرجات البناء.
- إعادة هيكلة الروابط دون إعادة توجيه. كل رابط قديم يصبح 404.
حالات 404 في Mythex
في Mythex تنشر من مساحة العمل، والواجهات الأمامية الثابتة تُنشر كمواقع ثابتة. إذا أعطت صفحة منشورة 404، فأعطِ الوكيل الرابط الدقيق، وهل يحدث ذلك عند التحديث أم عند النقر، وما الذي يُظهره تبويب Network، واطلب منه فحص التوجيه. انشر مرة أخرى بعد الإصلاح، لأن التطبيق الحي نسخة لقطة حتى تعيد النشر. إذا غيّرت المشروع مؤخراً والموقع الحي يبدو قديماً، فانشر مرة أخرى وأعد التحميل بالكامل (hard refresh). استخدم Fix with AI في نافذة النشر إذا فشل البناء. راجع كيف تنشر واستكشاف أخطاء النشر في الوثائق، ودليلنا عن تصحيح تطبيق بُني بالذكاء الاصطناعي.
قائمة مراجعة 404
- دوّنت الروابط الدقيقة التي تعطي 404، وهل ذلك عند النقر أم التحديث أم كليهما
- قاعدة SPA تعيد
index.htmlلمسارات التطبيق بحالة 200 - القاعدة تستثني الملفات الحقيقية و
/api/* - الموجّه لديه مسار شامل «غير موجود»
- مجلد مخرجات البناء هو ما يُنشر، ونجح البناء
- المسار الأساسي يطابق المكان الذي يُقدَّم منه التطبيق
- حالة أحرف أسماء الملفات تطابق كل مرجع
- مسارات الأصول تبدأ بـ
/ - نمط الشرطة المائلة في النهاية متسق
- الواجهات البرمجية منشورة وموجّهة في الإنتاج
- إعادة توجيه 301 للروابط القديمة
- اختبرت الروابط العميقة بلصقها في نافذة جديدة
الأسئلة
لماذا أحصل على 404 عندما أحدّث صفحة في تطبيق React الخاص بي؟
في تطبيق الصفحة الواحدة (SPA)، المسارات مثل /dashboard موجودة فقط داخل JavaScript. النقر على رابط يعمل لأن الموجّه (router) يتولاه في المتصفح، لكن تحديث الصفحة يطلب من الخادم ملفاً باسم /dashboard غير موجود. الحل قاعدة احتياطية (fallback) تعيد index.html لمسارات التطبيق.
كيف أضيف قاعدة الرجوع إلى index.html في Netlify أو Vercel أو Nginx؟
في Netlify، أضف ملف _redirects يحوي السطر /* /index.html 200. وفي Vercel، أضف rewrite في vercel.json يوجّه كل المسارات إلى /index.html. وفي Nginx، استخدم try_files $uri $uri/ /index.html; داخل كتلة location. راجع وثائق المزود لديك، فالقواعد تتغير.
لماذا تعطي صوري أو ملفاتي 404 بعد النشر؟
غالباً لأن الملف غير موجود في مخرجات البناء، أو لأن حالة الأحرف في المسار لا تطابق الملف الفعلي (الخوادم كثيراً ما تفرّق بين الحروف الكبيرة والصغيرة بينما حاسوبك لا يفعل)، أو لأن المسار نسبي بينما يجب أن يبدأ بشرطة مائلة.
هل يجب أن تُرجع الصفحة المفقودة حالة 404 حقيقية؟
نعم. اعرض صفحة «غير موجود» مفيدة، لكن بحالة 404 حيثما يسمح إعدادك. محركات البحث تعتبر رسالة «غير موجود» مع حالة 200 خطأً ناعماً (soft 404)، وهذا يهدر وقت الزحف ويربك الفهرسة.