برنامه‌نویسی

قابلیت‌های جدید Next.js ۱۰

قابلیت‌های جدید next.js ۱۰

مقدمه

اخیرا Next.js ۱۰ با بسیاری از ویژگی‌های هیجان انگیز منتشر شده است و شما می‌توانید برای کسب اطلاعات بیشتر از تغییرها و قابلیت‌های جدید به مقاله‌ی اصلی که در وبلاگ رسمی Next.js منتشر شده است، مراجعه کنید. بااین‌حال در این مقاله سعی داریم تا هر کدام از موارد را به‌صورت جداگانه به همراه تاثیر آن‌ها بر توسعه و تجربه‌ی کاربری، تجزیه و تحلیل کنیم.

شما می‌توانید با بررسی کدهای ذکر شده در این ریپازیتوری GitHub موارد ذکر شده در ادامه‌ی مقاله را آزمایش کنید و حتما مطمئن شوید که با دستور npm install تمام وابستگی‌های مربوط به پروژه را نصب و سپس با دستور npm run dev پروژه را اجرا کنید تا در آدرس localhost:3001 به خروجی پروژه دسترسی داشته باشید.

کامپوننت جدید next/image

کامپوننت image در next.js ۱۰

تیم توسعه‌ی Next.js در سال‌های گذشته سعی در بهبود سرعت سایت‌هایی داشته که با استفاده از این فریم‌ورک ساخته شده‌اند. برای مثال می‌توانیم به استراتژی‌های بهینه‌سازی شده‌ای مانند static generation و server-side rendering اشاره داشته باشیم و همچنین استفاده از JavaScript bundle باعث شده تا بارگیری کدهای JavaScript توسط مرورگر سریع‌تر شود. اگرچه این امر به بهینه‌سازی markup و تحول JavaScript در سایت‌ها کمک کرده است اما تصاویر به‌عنوان بخشی از آن سایت‌ها ارائه می‌شوند و تا قبل از این نسخه از Next.js، به بهینه‌سازی آن‌ها توجهی نشده بود.

مدیریت صحیح تصاویر تاثیر مهمی بر عملکرد سایت دارد:

  • تصاویر به‌طور پیش‌فرض بهینه‌سازی نمی‌شوند و در نهایت این موضوع باعث می‌شود تا حجم تصاویر به‌صورت نامتعارفی زیاد باشد.
  • تصاویر با اندازه‌های اصلی‌شان بارگیری می‌شوند درحالی که نسخه‌ی کوچکی از آن تصاویر در موبایل‌ها نمایش داده می‌شود.
  • اکثر این تصاویر در زمان ورود کاربر به سایت، خارج از محدوده‌ی نمایشگر کاربر هستند و تا زمانی‌که به سمت آن‌ها پیمایش نشود، نیازی به بارگیری آن تصاویر نیست.

کامپوننت Image که در Next.js ۱۰ معرفی شده است و کمک می‌کند تا مشکلات مربوط به بهینه‌سازی تصاویر را رفع کنیم و همچنین زحمت‌ توسعه‌دهندگان را کاهش می‌دهد. برای استفاده از این کامپوننت تنها نیاز است تا توسعه‌دهندگان تگ‌های <img> در HTML را با تگ <Image> جایگزین کنند.

مثالی از کد HTML:

<img src="/profile-picture.jpg" width="400" height="400" alt="Profile Picture">

و تبدیل آن به کد Next.js:

import Image from 'next/image';

<Image src="/profile-picture.jpg" width="400" height="400" alt="Profile Picture">

طبق گزارش‌هایی که در هر به‌روزرسانی توسط تیم توسعه Next.js ارائه می‌شود، در این نسخه تلاش شده تا تصاویر در این فریم‌ورک با همکاری تیم توسعه‌ی Next.js و تیم توسعه‌ی Google Chrome بهینه‌سازی شوند، حال نتیجه‌ی این همکاری باعث شده تا کامپوننت Image از موارد زیر پشتیبانی کند:

  • lazy loading و preloading
  • ارائه ابعاد تصویر که مانع از ایجاد تغییر در طرح سایت پس از بارگیری تصویر می‌شود

علاوه‌براین، تصاویر با حجم کم‌تر و با تبدیل شدن به فرمت جدید WebP، برای وبسایت‌ها بهینه‌تر شده‌اند. همچنین تصاویر در زمانی رندر می‌شوند که کاربر به سمت آن‌ها پیمایش کند و به‌این صورت زمان بارگیری سایت بهینه‌تر شده است. حال با درنظر گرفتن تمام این قابلیت‌ها که به لطف استفاده از کامپوننت جدید Image محقق می‌شوند، سروکار داشتن با تصاویر بسیار آسان‌تر و کارآمدتر شده است.

تاثیر در پروژه‌های واقعی

بیایید این قابلیت‌ها را با مثال‌هایی از پروژه‌های واقعی، بهتر درک کنیم و به بررسی آن‌ها بپردازیم. کدهای مربوط به کامپوننت Image را می‌توانید در همان ریپازیتوری که قبلا قرار داده بودیم در مسیر pages/test-image.js مشاهده کنید. البته باید اشاره داشته باشیم که تصاویر اصلی تقریبا ۱ مگابایت حجم دارند و فرمت آن‌‌ها .jpeg است. هنگامی که صفحه بارگیری می‌شود از طریق بخش Network می‌توانید ببینید که تصاویر از همان ابتدا بارگیری نمی‌شوند و قبل از رسیدن به تصاویر در زمانی‌که به پایین صفحه پیمایش می‌کنید، درخواست‌هایی ارسال می‌شود تا تصاویر بارگیری شوند. در gif زیر می‌توانید به‌وضوح این مورد را مشاهده کنید:

تاثیر کامپوننت image بر بارگیری تصاویر در next.js ۱۰

همچنین می‌توانید مشاهده ‌کنید که طرح صفحه‌‌ی وب حتی اگر تصویر کاملا بارگیری نشده باشد هم تغییری نمی‌کند زیرا Next.js ابعاد تصویری که می‌بایست بارگیری شود را محاسبه و به اندازه‌ی آن یک فضای خالی در DOM ایجاد می‌کند. نکته‌ی دیگری که باید به آن توجه داشته باشیم، بهینه‌سازی تصویر است که در بخش Network می‌توانید نتایج آن را مشاهده کنید:

بهینه‌سازی تصویر با کامپوننت image در next.js ۱۰

فرمت تصویر تغییر کرده و به فرمت webp که برای وب مناسب است، درآمده و ابعاد تصویر با حفظ نسبت طول به عرض بهینه‌سازی شده است. در نهایت به‌دلیل این بهینه‌سازی‌ها، شاهد کاهش اندازه‌ی تصویر به ۳۷ کیلوبایت هستیم که منجر به عملکرد بهتر تصاویر در همه‌ی دستگاه‌ها می‌شود.

پشتیبانی از Internationalization

پشتیبانی از internationalization در next.js ۱۰

بر اساس بیانیه رسمی Next.js:

احتمال ماندن کاربران در سایت شما با ترجمه سایت به زبان بومی آن‌ها، ۷۲ درصد افزایش می‌یابد و ۵۵ از کاربران گفته‌اند که فقط از سایت‌هایی با زبان بومی خود خریداری می‌کنند.

بنابراین با توجه به این بررسی‌ها لازم است تا از زبان بومی کاربرانی که اکثر بازدید کنندگان وبسایت شما را شکل می‌دهند، پشتیبانی کنید و در این نسخه از Next.js مسیری هموارتر از گذشته را پیش روی خود خواهید داشت زیرا از رایج‌ترین استراتژی‌های routing در این فریم‌ورک پشتیبانی می‌شود:

  • subpath routing: در این استراتژی، موقعیت کاربر مانند fr، en، nl به بخشی از URL تبدیل می‌شود و همه‌ی ترجمه‌های مورد نیاز برای موقعیت‌های مکانی مختلف در همان دامنه‌ی اصلی در دسترس است.
  • domain routing: در این استراتژی شاهد تغییر دامنه هستیم.

برای شروع کار با internationalization، باید کدهای زیر را به next.config.js اضافه کنیم:

module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    defaultLocale: 'en'
  }
}

با ایجاد یک فایل next.config.js در مسیر ریشه‌ی پروژه‌ی نمونه‌ی خود سعی می‌کنیم از internationalization استفاده کنیم. پس از انجام این کار و راه‌اندازی مجدد سرور می‌توانیم ببینیم که صفحه‌‌ای در مسیر localhost:3001/fr/test-image (نسخه‌ی فرانسوی یک صفحه با استراتژی subpath routing) در ریپازیتوری که قبلا برای شما قرار داده بودیم در دسترس است.

این صفحه‌ای است که به افرادی با تنظیمات زبان پیش‌فرض fr ارائه می‌شود، با ایجاد این تغییرها در Google Chrome:

تغییر زبان محلی در مرورگر chrome

و وارد شدن به مسیر مسیر اصلی پروژه، با استراتژی subpath به صفحه‌ی /fr ریدایرکت می‌شوید زیرا Next.js به‌طور خودکار زبان محلی پیش‌فرض مرورگر شما را شناسایی می‌کند.

subpath routing در next.js ۱۰

حال اگر می‌خواهید بدانید که Next.js چگونه زبان محلی مرورگر شما را تشخیص داده است باید به accept-language در headerهای ارسال شده برای بارگیری صفحه توجه کنید:

تغییر در headerهای ارسال شده به سرور با تغییر زبان محلی مرورگر chrome

Domain routing برخلاف subpath routing به پیکربندی‌های اضافی دیگری نیاز دارد:

module.exports = {
  i18n: {
    locales: ['en', 'fr'],
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en'
      },
      {
        domain: 'example.fr',
        defaultLocale: 'fr'
      }
    ]
  }
}

با این پیکربندی پس از ارسال درخواست به مسیر اصلی سایت، یک ریدایرکت انجام می‌شود تا کاربر به دامنه‌ی مورد نظر هدایت شود. اما شاید برای شما سوال شود که چگونه زبان محلی فعلی کاربر را شناسایی کنیم و بر اساس آن تصمیم بگیریم که به چه دامنه‌ای ریدایرکت شود.

برای این کار می‌توانید از useRouter که hookی از next/router محسوب می‌شود، استفاده کنید. ابتدا در کدهای زیر، زبان محلی مرورگر کاربر را توسط useRouter دریافت و پس از آن با کامپوننت Link، کاربر را به دامنه‌ی دلخواه هدایت می‌کنیم.

const router = useRouter();
// store the current locale
const currentLocale = router.locale;

// somewhere in the JSX, pass currentLocale to Link:
<Link
  href="/test-image" 
  locale={currentLocale}
>
...
</Link>

با این کار وقتی که بر روی لینکی در صفحه‌ی اصلی کلیک می‌کنیم به صفحه‌ی localhost:3001/fr/test-image ریدایرکت می‌شویم.

اگر با getStaticProps یا getServerSideProps کار می‌کنید نیز می‌توانید با استفاده از context object به عنوان state کارهای مشابهی انجام دهید:

هنگام pre-render کردن صفحه‌ها با getStaticProps یا getServerSideProps، داده‌های مربوط به زبان محلی پیش‌فرض مرورگر توسط contextها در اختیار شما قرار داده می‌شود.

مستندات Next.js

این‌ها خلاصه‌ای از پشتیبانی end-to-end locale بود که در Next.js ۱۰ معرفی شده است.

Next.js commerce

اضافه شدن next.js commerce به next.js ۱۰

Next.js با همکاری BigCommerce یک کیت به نام Next.js Commerce منتشر کرده که می‌توانید به کمک آن عملیات استقرار سایت فروشگاهی خود را تنها با چند کلیک انجام دهید. هیجان انگیزترین بخش استقرار سایت به کمک Next.js Commerce، بهره بردن از مزایای Next.js در سایت فروشگاهی‌تان است که برخی از آن‌ها عبارتند از:

  • file system مبتنی بر routing
  • splitting و bundling کدها
  • رندر هیبریدی با SSR و SSG
  • Fast refresh

تنها پیش‌نیازی که برای استقرار سایت توسط Next.js Commerce وجود دارد، پیکربندی فروشگاه BigCommerce است. البته قبل از شروع پیکربندی باید به صفحه‌ی اصلی Next.js Commerce بروید و بر روی Clone & Deploy کنید کنید تا این اجازه به شما داده شود که نمونه‌ای را در سایت خود مستقر کنید. مراحل پیکربندی نیز به شرح زیر هستند:

  • در BigCommerce ثبت نام کنید و اگر تابه‌حال فروشگاهی ایجاد نکرده‌اید، یک فروشگاه بسازید.
  • یک ریپازیتوری GitHub برای قرار دادن کدهای Next.js بسازید. push کردن به این ریپازیتوری باعث می‌شود تا عملیات استقرار مجددا انجام شود.
  • سایتی که با Next.js ساخته‌اید را deploy کنید.

دیگر قابلیت‌های برجسته‌ی Next.js ۱۰

پشتیبانی از React ۱۷

از این پس در Next.js ۱۰ شاهد پشتیبانی از React ۱۷ خواهیم بود و این بدان معناست که می‌توانید از آخرین قابلیت‌های React مانند JSX transform بهره‌مند شوید. در زمان کامپایل شدن نسخه‌های قبلی React، کدهای JSX برنامه به کدی معادل React.createElement() کامپایل می‌شدند و به‌همین دلیل برای کارکرد صحیح برنامه نیاز بود تا React در این scope وجود داشته باشد. اما از این پس با React ۱۷ به‌صورت خودکار JSX transformer توسط کامپایلر به برنامه import می‌شود.

در نهایت با این تفاسیر نیازی با import کردن React به فایل‌های .jsx نیست و با دستور زیر می‌توانید پروژه‌های قدیمی Next.js خود را به آخرین نسخه ارتقا دهید:

npm install next@latest react@latest react-dom@latest

Fast refresh

هر تغییری در فانکشن‌های getStaticProps و getServerSideProps باعث می‌شود تا عملیات‌ مورد نیاز بدون رفرش صفحه به‌صورت خودکار مجددا اجرا شوند. تمام صفحه‌های markdown که با next/mdx ایجاد شده‌اند نیز از Fast refresh پشتیبانی می‌کنند.

Third-party CSS

با این قابلیت تقسیم کدهای CSS برای یک کامپوننت خاص بدون اینکه آن را در _app.js وارد کنیم در بخشی جداگانه امکان‌پذیر شده است. موارد استفاده این قابلیت برای کدهایی است که فقط به یک کامپوننت خاص مربوط می‌شوند و در هیچ جای دیگری از کدهای ما مورد نیاز نیستند.

Auto-resolving در href

در نسخه‌های قبلی Next.js در حالی که از next/link برای dynamic routing استفاده می‌کردید نیاز بود تا به‌صورت زیر عمل کنید:

<Link href="/books/[bookId]" as={`/books/${bookId}`}>
  Harry Potter
</Link>

همان‌طور که در سناریو بالا شاهد هستید، href یک رشته‌ی متنی ثابت بود که در runtime نیز تغییری نمی‌کرد و یک فرمت برای route ارائه می‌داد. از طرفی دیگر as وجود داشت که به‌طور dynamic یک route برای ایجاد پیوند بین صفحه‌ها در اختیار ما قرار می‌داد. اما از این پس کدها در Next.js ۱۰ به‌صورت زیر هستند:

<Link href={`/book/${bookId}`}>
  Harry Potter
</Link>

در این سناریو فقط استفاده از پارامتر href اجباری است و می‌توانید as را به‌صورت اختیاری استفاده کنید.

Codemod CLI

Next.js به‌منظور ارتقا سریع‌تر برنامه‌ها برای دسترسی به ویژگی‌های جدیدتر و منسوخ کردن قابلیت‌های قدیمی، @next/codemod CLI را ارائه کرده است که در به‌روزرسانی کل برنامه و سازگاری آن کمک می‌کند. ایجاد سازگاری میان نسخه‌ها به این صورت است که کدهای منسوخ شده حذف و با آخرین تغییرها جایگزین می‌شوند و تمام این کارها فقط با یک دستور انجام می‌شود:

npx @next/codemod <transform> <path>

Blocking fallback برای getStaticPaths

با تنظیم کردن fallback: 'blocking' هنگام return کردن getStaticPaths باعث می‌شود تا در زمانی‌که هیچ static fallback برای مرورگر ارسال نمی‌شوند و initial request برای pre-rendering صفحه منتظر مانده است، blocking behavior فعال شود. پس از رندر اولیه، صفحه برای درخواست‌های بعدی مجددا مورد استفاده قرار می‌گیرد.

پشتیبانی از Redirect

در حالی که از getStaticProps و getServerSideProps استفاده می‌کنید، می‌توانید یک فیلد جدید به نام Redirect را به‌صورت زیر return کنید:

export function getStaticProps() {
  return {
    // returns a redirect to an internal page `/another-page`
    redirect: {
      destination: '/another-page',
      permanent: false
    }
  }
}

export function getServerSideProps() {
  return {
    // returns a redirect to an external domain `example.com`
    redirect: {
      destination: 'https://example.com',
      permanent: false
    }
  }
}

مقصد در پیکربندی redirect برای هدایت درخواست مشخص می‌شود. برای مشاهده‌ی خروجی کدهای بالا می‌توانید از آدرس localhost/test-redirect بازدید کنید و همان‌طور که مشاهده خواهید کرد به صفحه‌ی /fast-refresh هدایت می‌شوید زیرا این صفحه به‌عنوان مقصد در پیکربندی redirect مشخص شده است.

پشتیبانی از notFound

مشابه پیکربندی redirect شاهد return شدن notFound در responseها با مقدار true هستیم که باعث می‌شود یک صفحه‌ی 404 پیش‌فرض با استاتوس کد 404 به کاربر بازگردانده شود. این قابلیت می‌تواند در هنگام اجرای برخی منطق‌های تجاری در فانکشن getStaticProps مفید باشد اما بدیهی است که ما از این route در برنامه‌‌ی خود پشتیبانی نمی‌کنیم. بنابراین به‌جای نمایش این اطلاعات در یک UI سفارشی‌سازی شده یا نوشتن یک redirection logic در صفحه، می‌توانیم یک flag از getStaticProps را که به عملیات redirect رسیدگی می‌کند، return کنیم.

export async function getStaticProps() {
  let notFound = false;

  // perform some business logic here.
  // Got to know that the page need not show up
  notFound = true;

  return {
    notFound: notFound
  }
}

جمع‌بندی

به‌طور کلی این نسخه شامل پیشرفت‌های عمده‌ای در بخش توسعه و تجربه‌ی کاربری بوده است. علاوه‌براین‌ها می‌توانید این به‌روزرسانی اصلی Next.js را بدون مغایرت با نسخه‌های قبل امتحان کنید. بنابراین اگر از نسخه‌های قبلی Next.js استفاده می‌کنید، اکنون زمان مناسبی برای به‌روزرسانی است.

منبع: https://blog.logrocket.com/whats-new-in-next-js-10