ساخت Dark Mode در Next.js بدون پرش نوری (Flash)
ساخت Dark Mode ساده به نظر میرسد. اما بعد، با آن پرش نوری (flash) مواجه میشوید.
وقتی کاربر صفحه شما را بارگذاری میکند، سرور تم پیشفرض را ارسال میکند. کاربر برای کسری از ثانیه یک صفحه سفید میبیند و سپس تم تاریک اعمال میشود. این یک تجربه کاربری بد است.
مشکل اینجاست که سرور نمیتواند localStorage را بخواند. سرور تنها زمانی از تم مطلع میشود که مرورگر کدهای JavaScript شما را اجرا کند.
روش رفع این مشکل اینجاست.
راه حل: اسکریپت درونخطی (Inline Script)
شما باید تم را قبل از شروع کار React اعمال کنید. یک اسکریپت کوچک در تگ <head> قرار دهید. این اسکریپت تنظیمات کاربر را میخواند و بلافاصله کلاس dark را اضافه میکند.
از این مراحل استفاده کنید:
- یک اسکریپت در
<head>مربوط بهRootLayoutخود برای بررسیlocalStorageاضافه کنید. - از
suppressHydrationWarningدر تگ<html>استفاده کنید. این کار باعث میشود React بابت عدم تطابق تم (mismatch) خطا ندهد. - از یک
ThemeProviderبرای مدیریت وضعیت (state) و همگامسازی باlocalStorageاستفاده کنید. - از متغیرهای CSS در کنار Tailwind برای انتقال نرم رنگها استفاده کنید.
چرا این روش کار میکند: اسکریپت قبل از رندر شدن صفحه اجرا میشود و از پرش بصری جلوگیری میکند.
مدیریت تصاویر
تصاویر اغلب در حالتهای روشن و تاریک به نسخههای متفاوتی نیاز دارند. شما دو انتخاب دارید:
- روش CSS: از
display: noneوdisplay: blockاستفاده کنید تا تصاویر را بر اساس کلاس.darkجابهجا کنید. این سریعترین روش است. - روش کلاینت (Client): از کامپوننتی استفاده کنید که تم را بررسی کرده و منبع تصویر (image source) مناسب را انتخاب میکند.
نکته حرفهای برای محتوای سمت سرور
اگر نیاز دارید سرور برای نمودارها یا محتواهای سنگین، از تم مطلع باشد، به جای localStorage از کوکیها (cookies) استفاده کنید.
- تم را در یک کوکی ذخیره کنید.
- از middleware در Next.js برای خواندن آن کوکی استفاده کنید.
- تم را از طریق هدرها (headers) به layout خود منتقل کنید.
این کار به سرور اجازه میدهد تا از همان ابتدا HTML صحیح را ارسال کند.
خلاصهای برای داشتن سیستمی بدون پرش نوری:
• استفاده از یک اسکریپت درونخطی در <head>
• استفاده از suppressHydrationWarning
• مدیریت وضعیت با یک Context Provider
• گوش دادن به تغییرات تنظیمات سیستم (system preference)
این رویکرد برای اپلیکیشنهای عملیاتی (production) مناسب است و جابهجایی آنی و عدم وجود پرش نوری را تضمین میکند.