چطور صفحهی سفید خالی را در اپ وب برطرف کنیم
صفحهی سفید خالی تقریباً همیشه یکی از دو چیز را نشان میدهد: جاوااسکریپت اپ پیش از کشیدن هر چیزی کرش کرده، یا اصلاً هرگز بارگذاری نشده است. کنسول مرورگر را باز کنید (راستکلیک → Inspect → Console) و اولین خطای قرمز را بخوانید، سپس تب Network را برای فایلهایی که بارگذاری نشدهاند بررسی کنید. بیشتر علتها متغیر محیطی گمشده، base path اشتباه، بیلدی که تمام نشده، یا کرش یک کامپوننت هستند.
این راهنما برای اپهای تکصفحهای ساختهشده با React، Vue یا فریمورکهای مشابه است (از جمله اپهایی که سازندههای هوش مصنوعی میسازند) که صفحهی خالی در آنها رایجترین است.
چرا صفحه سفید است؟
یک اپ تکصفحهای مدرن (SPA) برای مرورگر یک فایل HTML تقریباً خالی میفرستد، تقریباً به این شکل:
<body>
<div id="root"></div>
<script type="module" src="/assets/index-a1b2c3.js"></script>
</body>
بعد جاوااسکریپت کل صفحه را داخل آن div خالی میسازد. اگر اسکریپت بارگذاری نشود، یا پیش از رندر خطا بدهد، آن div خالی میماند و شما فقط سفیدی میبینید. صفحه به شکل قابلدیدنی «خراب» نیست؛ فقط هرگز کشیده نشده است.
به همین دلیل رفع مشکل همیشه از ابزارهای توسعهدهنده شروع میشود، نه از خود صفحه.
گام ۱: کنسول را بخوانید
ابزارهای توسعهدهنده را باز کنید: روی صفحه راستکلیک کنید و Inspect را انتخاب کنید، یا F12 بزنید (Cmd+Option+I روی مک). به تب Console بروید و صفحه را رفرش کنید.
به اولین خطای قرمز نگاه کنید؛ خطاهای بعدی اغلب پیامد آن هستند. آنچه میگوید علت را نشان میدهد:
| پیام کنسول (شکل معمول) | یعنی چه | برو به |
|---|---|---|
Cannot read properties of undefined (reading '...') | کد دادهای را انتظار داشت که نبود | گام ۴ |
... is not defined / ... is not a function | یک import، متغیر یا تنظیم گمشده | گام ۴ یا گام ۳ |
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html" | نشانی یک اسکریپت بهجای JavaScript، صفحهی HTML برگردانده | گام ۲ |
Uncaught SyntaxError: Unexpected token '<' | همان موضوع: HTML بهجای JavaScript | گام ۲ |
supabaseUrl is required، Missing API key یا مشابه | یک متغیر محیطی خالی است | گام ۳ |
Access to fetch ... has been blocked by CORS policy | یک درخواست به دامنهی دیگری مسدود شده | رفع خطاهای CORS |
| هیچ خطایی نیست | رندر انجام شده ولی چیزی نشان نمیدهد، یا CSS آن را پنهان کرده | گام ۶ |
متن کامل خطا، شامل نام فایل و شمارهی خط، را کپی کنید. اگر از یک سازندهی هوش مصنوعی استفاده میکنید، آن را مستقیم در چت بچسبانید.
گام ۲: بررسی کنید فایلها بارگذاری شدهاند
تب Network را باز کنید، گزینهی Disable cache را فعال کنید و صفحه را رفرش کنید. درخواستهای فایلهای .js و .css را ببینید.
- وضعیت 404 روی یک فایل JavaScript: صفحه فایلی را میخواهد که روی سرور نیست.
- وضعیت 200 ولی نوع
text/html: سرور بهجای اسکریپت یک صفحه (اغلب خودindex.html، بهخاطر بازگشت SPA) برگردانده است. علت یکی است: فایل جایی نیست که صفحه انتظارش را دارد.
دلایل رایج:
base path اشتباه. اگر اپ داخل یک زیرپوشه سرو میشود، مثل example.com/app/، ولی برای بارگذاری فایلها از /assets/... بیلد شده، هر درخواست اسکریپت به جای اشتباهی میرود. در Vite این گزینهی base در vite.config است؛ در Create React App فیلد homepage؛ در Next.js گزینهی basePath. باید با جایی که اپ واقعاً سرو میشود یکی باشد.
index.html قدیمی. ابزارهای بیلد به فایلها نامهایی با هش محتوا میدهند، مثل index-a1b2c3.js. بعد از یک دیپلوی جدید، فایل قدیمی دیگر نیست. اگر مرورگر یا CDN هنوز index.html قدیمی را کش کرده باشد، آن فایل قدیمی را میخواهد و چیزی نمیگیرد. یک Hard refresh (Cmd+Shift+R یا Ctrl+Shift+R) این را تأیید میکند. راهحل بلندمدت این است که index.html با هدر کش کوتاه یا بدون کش سرو شود، در حالی که فایلهای هشدار برای مدت طولانی کش میشوند.
بیلد تمام نشده یا دیپلوی نشده. اگر بیلد شکست خورده، میزبان ممکن است پوشهی خروجی قدیمی یا خالی را سرو کند. لاگ بیلد را برای خطاها بررسی کنید.
پوشهی اشتباه منتشر شده. میزبان باید خروجی بیلد را سرو کند (معمولاً dist یا build)، نه پوشهی سورس پروژه. سرو کردن سورس، یک index.html میدهد که به /src/main.tsx اشاره میکند و مرورگرها نمیتوانند آن را اجرا کنند.
گام ۳: متغیرهای محیطی را بررسی کنید
اپهای فرانتاِند اغلب تنظیماتی مثل نشانی API یا یک کلید عمومی را در زمان بیلد میخوانند. اگر یک متغیر روی بیلد عملیاتی گم باشد، کدی مثل createClient(undefined, undefined) بلافاصله خطا میدهد و صفحه سفید میشود.
نکاتی که باید بدانید:
- در Vite فقط متغیرهایی که با
VITE_شروع میشوند در کد مرورگر در دسترساند و باimport.meta.env.VITE_NAMEخوانده میشوند. در Create React App پیشوندREACT_APP_و در Next.js پیشوندNEXT_PUBLIC_است. - این مقادیر موقع بیلد داخل کد قرار میگیرند. اضافه کردن متغیر بعد از بیلد هیچ اثری ندارد، تا وقتی دوباره بیلد و دیپلوی کنید.
- محیط پیشنمایش یا ماشین محلی ممکن است فایل
.envداشته باشد که بیلد عملیاتی ندارد. همان متغیرها را روی میزبان تنظیم کنید. - هر چیزی با این پیشوندها در جاوااسکریپت عمومی قرار میگیرد. فقط مقادیر عمومی را آنجا بگذارید، هرگز کلید مخفی را.
یک آزمون سریع: پیام خطا در کنسول را برای undefined کنار نام یک تنظیم جستجو کنید، یا بپرسید:
صفحهی منتشرشدهی اپ خالی نشان میدهد. هر متغیر محیطیای که فرانتاِند میخواند را فهرست کن، بررسی کن کدامها در بیلد عملیاتی گم یا خالیاند، و اگر یکی گم بود، بهجای صفحهی خالی یک پیام خطای روشن نشان بده.
گام ۴: کرش را برطرف کنید
اگر کنسول یک خطای عادی جاوااسکریپت نشان میدهد، کد هنگام رندر کرش کرده است. علتهای رایج در اپهای ساختهشده با هوش مصنوعی:
- داده هنوز بارگذاری نشده. یک کامپوننت
user.nameرا میخواند پیش از آنکهuserبرسد. راهحل یک حالت بارگذاری یا optional chaining (user?.name) است. - دادهی خالی. یک حساب جدید هنوز رکوردی ندارد و کد فرض میکند فهرست حداقل یک آیتم دارد.
- شکل غیرمنتظرهی داده. یک API بهجای فهرستی که کد انتظارش را داشت، یک شیء خطا برگردانده.
- یک import گمشده بعد از اینکه فایلی تغییر نام داده یا جابهجا شده.
- استفاده از API مخصوص مرورگر در هنگام رندر سمت سرور، مثل
windowیاlocalStorageدر یک کامپوننت سرور Next.js.
خطای کامل، صفحه و اینکه با چه حسابی وارد شده بودید را به هوش مصنوعی بدهید:
صفحهی داشبورد برای کاربران جدید خالی است. کنسول:
TypeError: Cannot read properties of undefined (reading 'map')درProjectList.tsx:18. برای حساب من که پروژه دارد کار میکند. آن را طوری درست کن که حساب خالی «هنوز پروژهای نیست» نشان دهد، و یک حساب جدید را در پیشنمایش بررسی کن.
گام ۵: یک error boundary اضافه کنید
در React، یک کامپوننت که کرش میکند میتواند کل اپ را از روی صفحه بردارد، و به همین دلیل یک باگ کوچک یک صفحهی کاملاً خالی میسازد. error boundary کامپوننتی است که خطاهای رندر زیر خودش را میگیرد و بهجایش یک پیام جایگزین نشان میدهد.
یک error boundary دور مسیرهای اصلی اضافه کن که پیام «مشکلی پیش آمد» با دکمهی بارگذاری مجدد نشان دهد و خطا را در کنسول ثبت کند. هدر و ناوبری را بیرون از آن نگه دار تا همچنان نمایش داده شوند.
این باگ را برطرف نمیکند، اما بازدیدکننده بهجای صفحهی خالی یک پیام میبیند و شما میبینید کجا خراب شده است.
گام ۶: بدون خطا ولی باز هم خالی
اگر کنسول تمیز است و اسکریپتها بارگذاری میشوند:
- تب Elements را بررسی کنید. آیا داخل
<div id="root">محتوایی هست؟ اگر بله، رندر شده ولی نامرئی است: متن سفید روی سفید،opacity: 0،display: none، یا یک عنصر تمامصفحه که رویش را گرفته. - روتر را بررسی کنید. اگر هیچ مسیری با نشانی فعلی نخواند و مسیر «پیدا نشد» نباشد، برخی روترها چیزی رندر نمیکنند. یک مسیر catch-all اضافه کنید که صفحهی ۴۰۴ نشان دهد.
- نقطهی اتصال را بررسی کنید. کد باید داخل عنصری بچسبد که وجود دارد. اگر
index.htmlدارایid="app"باشد و کد دنبالrootبگردد، هیچچیز ظاهر نمیشود (و React معمولاً خطایی ثبت میکند). - یک افزونهی مرورگر را بررسی کنید. یک پنجرهی خصوصی را امتحان کنید. مسدودکنندههای تبلیغ گاهی اسکریپتهایی با نامهایی مثل
analyticsیاadsرا مسدود میکنند.
فقط بعد از رفرش یک صفحه خالی میشود؟
اگر صفحهی اصلی کار میکند ولی رفرش /dashboard صفحهی خالی یا ۴۰۴ نشان میدهد، سرور نمیداند برای مسیرهای اپ باید index.html را بفرستد. این یک مشکل بازگشت مسیریابی است که در چطور خطای ۴۰۴ بعد از دیپلوی را برطرف کنیم پوشش داده شده است.
اشتباهات رایج
- خواندن آخرین خطا بهجای اولین. اولین خط قرمز معمولاً علت است.
- تنظیم متغیرهای محیطی بدون بیلد مجدد. متغیرهای فرانتاِند در زمان بیلد ثابت میشوند.
- آزمایش فقط با حساب خودتان. کرش حساب خالی یکی از رایجترین علتهای صفحهی سفید است.
- فرض اینکه دیپلوی موفق بوده. پیش از اشکالزدایی کد، لاگ بیلد را بررسی کنید.
- مقصر دانستن کش مرورگر برای همهچیز. یک Hard refresh در چند ثانیه آن را رد میکند؛ اگر صفحه همچنان خالی است، مشکل جای دیگری است.
صفحهی خالی در Mythex
اگر پیشنمایش خالی است، ابتدا بررسی کنید اپ اجرا است (Code → terminal را باز کنید)، سپس از Mythex بخواهید سرور درست را راه بیندازد، روی Refresh در نوار ابزار پیشنمایش کلیک کنید، یا از /fix استفاده کنید. برای یک نشانی منتشرشدهی خالی، مستندات پیشنهاد میکنند یک دقیقه صبر کنید و Hard refresh بزنید، پیش از انتشار تأیید کنید متغیرهای محیطی و پایگاه داده تنظیم شدهاند، و سهمیهی میزبانیتان را بررسی کنید. یادتان باشد اپ منتشرشده یک نسخهی ثابت است: بعد از رفع مشکل دوباره منتشر کنید. اگر یک تغییر باعث آن شده، Revert to this point روی آخرین پاسخ خوب، پروژه را به عقب برمیگرداند. عیبیابی و عیبیابی انتشار را در مستندات ببینید و راهنمای کلی ما دربارهی عیبیابی یک اپ ساختهشده با هوش مصنوعی را.
فهرست بررسی صفحهی سفید
- اولین خطای قرمز در کنسول را خواندهام
- در تب Network فایلهای
.js/.cssکه ۴۰۴ میدهند یا HTML برمیگردانند را بررسی کردهام - base path با جایی که اپ سرو میشود یکی است
- بیلد تمام شده و پوشهی خروجی بیلد همان چیزی است که منتشر میشود
- همهی متغیرهای محیطی فرانتاِند روی بیلد عملیاتی تنظیم شده، و سپس بیلد دوباره انجام شده
- کرش برطرف شده، از جمله برای حسابهای خالی و جدید
- error boundary برای نشان دادن پیام در کرشهای بعدی وجود دارد
- مسیر catch-all برای نشانیهای ناشناخته وجود دارد
- بعد از Hard refresh و در یک پنجرهی خصوصی آزمایش کردهام
پرسشها
چرا اپ React من صفحهی سفید خالی نشان میدهد؟
معمولاً چون جاوااسکریپت پیش از رندر شدن چیزی کرش کرده، یا فایل جاوااسکریپت هرگز بارگذاری نشده. کنسول مرورگر را باز کنید: خطای قرمز آنجا میگوید کدام و در کدام فایل و خط رخ داده.
چرا اپم روی سیستم محلی کار میکند ولی بعد از دیپلوی صفحهی خالی میشود؟
رایجترین علتها: متغیرهای محیطی که برای بیلد عملیاتی تنظیم نشدهاند، فایلهای JavaScript و CSS که از مسیر اشتباه درخواست میشوند (ناهماهنگی base path)، و یک index.html قدیمی در کش که به فایلهایی اشاره میکند که دیگر وجود ندارند.
معنی «Failed to load module script» چیست؟
مرورگر یک فایل JavaScript خواسته و بهجایش یک صفحهی HTML گرفته، معمولاً index.html سایت یا یک صفحهی خطا. مسیر فایل اشتباه است یا فایل روی سرور وجود ندارد؛ پس خروجی بیلد و تنظیم base path اپ را بررسی کنید.
چطور نگذارم یک باگ کل صفحه را خالی کند؟
یک error boundary اضافه کنید. در React، error boundary کامپوننتی است که خطاهای رندر را در بخشی از صفحه که زیرش قرار دارد میگیرد و بهجای از هم پاشیدن همهچیز، یک پیام جایگزین نشان میدهد.