قابلیتهای جدید Next.js ۱۰
۸ دی ۱۳۹۹
مقدمه
اخیرا Next.js ۱۰ با بسیاری از ویژگیهای هیجان انگیز منتشر شده است و شما میتوانید برای کسب اطلاعات بیشتر از تغییرها و قابلیتهای جدید به مقالهی اصلی که در وبلاگ رسمی Next.js منتشر شده است، مراجعه کنید. بااینحال در این مقاله سعی داریم تا هر کدام از موارد را بهصورت جداگانه به همراه تاثیر آنها بر توسعه و تجربهی کاربری، تجزیه و تحلیل کنیم.
شما میتوانید با بررسی کدهای ذکر شده در این ریپازیتوری GitHub موارد ذکر شده در ادامهی مقاله را آزمایش کنید و حتما مطمئن شوید که با دستور npm install
تمام وابستگیهای مربوط به پروژه را نصب و سپس با دستور npm run dev
پروژه را اجرا کنید تا در آدرس localhost:3001
به خروجی پروژه دسترسی داشته باشید.
کامپوننت جدید next/image
تیم توسعهی 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 زیر میتوانید بهوضوح این مورد را مشاهده کنید:
همچنین میتوانید مشاهده کنید که طرح صفحهی وب حتی اگر تصویر کاملا بارگیری نشده باشد هم تغییری نمیکند زیرا Next.js ابعاد تصویری که میبایست بارگیری شود را محاسبه و به اندازهی آن یک فضای خالی در DOM ایجاد میکند. نکتهی دیگری که باید به آن توجه داشته باشیم، بهینهسازی تصویر است که در بخش Network میتوانید نتایج آن را مشاهده کنید:
فرمت تصویر تغییر کرده و به فرمت webp
که برای وب مناسب است، درآمده و ابعاد تصویر با حفظ نسبت طول به عرض بهینهسازی شده است. در نهایت بهدلیل این بهینهسازیها، شاهد کاهش اندازهی تصویر به ۳۷ کیلوبایت هستیم که منجر به عملکرد بهتر تصاویر در همهی دستگاهها میشود.
پشتیبانی از Internationalization
بر اساس بیانیه رسمی 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:
و وارد شدن به مسیر مسیر اصلی پروژه، با استراتژی subpath به صفحهی /fr
ریدایرکت میشوید زیرا Next.js بهطور خودکار زبان محلی پیشفرض مرورگر شما را شناسایی میکند.
حال اگر میخواهید بدانید که Next.js چگونه زبان محلی مرورگر شما را تشخیص داده است باید به accept-language
در headerهای ارسال شده برای بارگیری صفحه توجه کنید:
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 کردن صفحهها با
مستندات Next.jsgetStaticProps
یاgetServerSideProps
، دادههای مربوط به زبان محلی پیشفرض مرورگر توسط contextها در اختیار شما قرار داده میشود.
اینها خلاصهای از پشتیبانی end-to-end locale بود که در Next.js ۱۰ معرفی شده است.
Next.js commerce
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 استفاده میکنید، اکنون زمان مناسبی برای بهروزرسانی است.