ساخت 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) مناسب است و جابه‌جایی آنی و عدم وجود پرش نوری را تضمین می‌کند.

Source: https://dev.to/aon_infotech_3a1b6ff525fc/building-a-dark-mode-system-in-nextjs-app-router-without-layout-flash-5gf9