بررسی تغییرات نسخه ۱۵ Next.js

تیم توسعه Next.js یک نسخه اولیه از ۱۵ Next.js منتشر کرده است تا این امکان را برای توسعه‌دهندگان فراهم کند که قبل از انتشار نسخه پایدار، بتوانند ویژگی‌های جدید را مورد آزمایش قرار دهند.

تغییراتی که در نسخه ۱۵ Next.js، که نسخه کاندید انتشار می‌باشد، صورت گرفته است به طور خلاصه عبارتند از:

  • React: پشتیبانی از نسخه ۱۹ React، پشتیبانی از React Compiler و بهبود خطای hydration
  • Caching: عدم ذخیره‌سازی درخواست‌های fetch، GET Route Handlerها و client navigationها به‌طور پیش‌فرض در حافظه cache
  • Partial Prerendering: افزودن گزینه پیکربندی جدید Layout و Page برای لود تدریجی کامپوننت‌ها
  • next/after: معرفی API جدید برای اجرای کد پس از اتمام stream توسط response
  • create-next-app: به‌روزرسانی طراحی و افزودن یک flag جدید به منظور فعال کردن Turbopack در توسعه لوکال
  • Bundling پکیج‌های اکسترنال: افزودن گزینه‌های پیکربندی جدید برای App و Pages Router

بررسی پشتیبانی از React 19

نسخه ۱۵ Next.js اکنون از نسخه ۱۹ React، که شامل ویژگی‌های جدید برای کلاینت و سرور، مانند actionها، می‌باشد پشتیبانی می‌کند. در این نسخه App Router بر روی canary channel ، که مربوط به React بوده و برای فریم‌ورک‌ها می‌باشد، ساخته شده است و به توسعه‌دهندگان این امکان را می‌دهد تا قبل از انتشار نسخه ۱۹ از این APIهای جدید React استفاده کرده و نظرات خود را ارائه نمایند.

باید به این نکته توجه داشته باشیم که ممکن است برخی از کتابخانه‌های third party هنوز با نسخه ۱۹ React سازگار نباشند.

بررسی پشتیبانی از React Compiler

React Compiler یک کامپایلر آزمایشی جدید است که توسط تیم React در Meta ایجاد شده است. کامپایلر کد ما را در سطح عمیقی از جاوااسکریپت و قوانین React درک می‌کند، که به آن اجازه می‌دهد تا بهینه‌سازی‌های خودکار را به کدی که داریم اضافه نماید. کامپایلر میزان ذخیره‌سازی دستی که توسعه‌دهندگان باید از طریق APIهایی مانند useMemo و useCallback انجام دهند را کاهش می‌دهد. همین موضوع باعث می‌شود تا کدها ساده‌تر شوند، نگه‌داری آن‌ها آسان‌تر شده و کم‌تر مستعد بروز خطا باشند.

در نسخه ۱۵ Next.js پشتیبانی از React Compiler هم اضافه شده است.

برای استفاده از آن babel-plugin-react-compiler را نصب می‌کنیم:

npm install babel-plugin-react-compiler

سپس، گزینه experimental.reactCompiler را در next.config.js اضافه می‌نماییم:

const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

به صورت اختیاری، می‌توانیم کامپایلر را برای اجرا در حالت “opt-in” به صورت زیر پیکربندی کنیم:

const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

توجه به این نکته لازم است، React Compiler در حال حاضر فقط از طریق یک افزونه Babel در Next.js امکان‌پذیر می‌باشد که استفاده از آن می‌تواند منجر به کندتر شدن زمان build شود.

بررسی بهبودهای خطای Hydration

نسخه ۱۴٫۱ Next.js بهبودهایی را در پیام‌های خطا و خطاهای hydration ایجاد کرد. در نسخه ۱۵ Next.js تیم توسعه با افزودن نمای خطای hydration بهبودیافته به تلاش خود در زمینه بهبود بیشتر آن‌ها ادامه می‌دهد. خطاهای hydration اکنون سورس کد خطا را با پیشنهاداتی در مورد نحوه رسیدگی به این مشکل نشان می‌دهد.

بررسی به‌روزرسانی‌های مربوط به Caching

App Router موجود در Next.js با پیش‌فرض‌های caching منتشر شد. این‌ها به گونه‌ای طراحی شده‌اند که به‌طور پیش‌فرض کارآمدترین گزینه را، با قابلیت انصراف در صورت لزوم، ارائه دهند.

تیم توسعه Next.js براساس بازخوردهایی که از توسعه‌دهندگان دریافت کرده بودند، caching و نحوه تعامل آن‌ها با پروژه‌هایی مانند Partial Prerendering (PPR) و کتابخانه‌های third party را با استفاده از fetch دوباره مورد ارزیابی قرار دادند.

در نسخه Next.js 15، پیش‌فرض ذخیره‌سازی برای درخواست‌های fetch، GETRoute Handlerها و Client Router Cache را عوض می‌کنیم. یعنی این که آن را از پیش‌فرض cached به پیش‌فرض uncached تغییر می‌دهیم. اما اگر قصد داریم رفتار قبلی را حفظ نماییم، می‌توانیم با انتخاب caching به کار خود ادامه دهیم.

طبق گفته تیم توسعه Next.js، آن‌ها به کار خود در رابطه با بهبود حافظه caching ادامه خواهند داد و در ماه‌های آینده جزئیات بیشتری را در اطلاعیه Next.js 15 GA به اشتراک خواهند گذاشت.

بررسی عدم cache شدن پیش‌فرض درخواست fetch

Next.js از گزینه Web fetch API cache برای پیکربندی نحوه تعامل درخواست fetch سمت سرور با حافظه cache HTTP پایدار فریم‌ورک استفاده می‌کند:

fetch('https://...', { cache: 'force-cache' | 'no-store' });
  • no-store – در هر درخواست، منبعی را از یک سرور ریموت دریافت کرده و کش را به‌روزرسانی نمی‌کنیم.
  • force-cache – در هر درخواست، منبعی را از کش (در صورت وجود) یا یک سرور ریموت دریافت کرده و کش را به‌روزرسانی می‌کنیم.

در نسخه Next.js 14، در صورتی که گزینه cache ارائه نشده باشد، به‌طور پیش‌فرض از force-cache استفاده می‌شود، مگر اینکه از یک تابع داینامیک یا گزینه پیکربندی داینامیک استفاده شده باشد.

در نسخه Next.js 15، اگر گزینه cache ارائه نشده باشد، به‌طور پیش‌فرض از no-store استفاده می‌شود. این بدان معناست که درخواست‌های fetch به‌طور پیش‌فرض در حافظه cache ذخیره نمی‌گردد.

همچنین می‌توانیم درخواست‌های fetch caching را از طریق موارد زیر انتخاب کنیم:

  • تنظیم گزینه cache بر روی force-cache در یک فراخوانی fetch واحد
  • تنظیم گزینه پیکربندی route dynamic روی 'force-static' برای یک route واحد
  • تنظیم گزینه پیکربندی route fetchCache بر روی 'default-cache' برای لغو همه درخواست‌های fetch در یک Layout یا Page برای استفاده از force-cache، مگر اینکه آن‌ها به صراحت گزینه cache خود را مشخص کنند.

بررسی عدم cache شدن پیش‌فرض GET Route Handlerها

در نسخه ۱۴، Route Handlerهایی که از متد GET HTTP استفاده می‌کردند به‌طور پیش‌فرض در حافظه cache ذخیره می‌شدند، مگر اینکه از یک تابع داینامیک یا گزینه پیکربندی داینامیک استفاده کنند. در نسخه Next.js 15، توابع GET به صورت پیش‌فرض در حافظه cache ذخیره نمی‌شوند.

ما همچنین می‌توانیم با استفاده از یک گزینه پیکربندی route استاتیک مانند export dynamic = 'force-static'، کش کردن را انتخاب نماییم.

Route Handlerهای ویژه مانند sitemap.ts، opengraph-image.tsx، icon.tsx و سایر فایل‌های متادیتا به‌طور پیش‌فرض ثابت می‌مانند، مگر اینکه از توابع داینامیک یا گزینه‌های پیکربندی داینامیک استفاده کنند.

بررسی عدم cache شدن پیش‌فرض Page componentها توسط Client Router Cache 

در نسخه Next.js 14.2.0، تیم توسعه یک flag آزمایشی staleTimes را معرفی کرد تا امکان پیکربندی سفارشی Router Cache را فراهم کند.

در نسخه Next.js 15، این flag همچنان قابل دسترسی است، اما تیم توسعه در حال تغییر رفتار پیش‌فرض هست تا staleTime از ۰ برای سگمنت‌های Page داشته باشد. این بدان معناست که در حین navigate کردن در برنامه خود، کلاینت همیشه آخرین داده‌ها را از کامپوننت(های) Page که به عنوان بخشی از navigation فعال می‌شوند، منعکس می‌کند. با این حال، هنوز رفتارهای مهمی وجود دارد که بدون تغییر باقی می‌مانند:

  • داده‌های layout به اشتراک‌گذاشته‌شده برای ادامه پشتیبانی از partial rendering، از سرور بازیابی نمی‌شوند.
  • برای اطمینان از اینکه مرورگر می‌تواند موقعیت اسکرول را بازیابی کند، پیمایش Back/forward همچنان از حافظه cache بازیابی می‌شود.
  • Loading.js به مدت ۵ دقیقه (یا مقدار پیکربندی staleTimes.static) در حافظه cache باقی می‌ماند.

با تنظیم پیکربندی زیر می‌توانیم رفتار کش Client Router Cache را انتخاب کنیم:

const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
module.exports = nextConfig;

بررسی پذیرش افزایشی Partial Prerendering

در نسخه ۱۴ Next.js، تیم توسعه Partial Prerendering(PPR) را که رندر استاتیک و داینامیک را در یک صفحه باهم ترکیب می‌کند، معرفی کرد.

Next.js در حال حاضر به صورت پیش‌فرض رندر استاتیک را ارائه می‌کند، مگر اینکه از توابع داینامیک مانند cookies()، headers() و درخواست‌های داده ذخیره نشده استفاده کنیم. این APIها یک مسیر کامل را برای رندر داینامیک انتخاب می‌کنند. ما می‌توانیم با استفاده از PPR، هر رابط کاربری داینامیک را در یک حالت Suspense قرار دهیم. هنگامی که یک درخواست جدید مطرح می‌شود، Next.js بلافاصله یک پوسته HTML استاتیک ارائه می‌کند، سپس بخش‌های داینامیک را در همان درخواست HTTP رندر و استریم می‌نماید.

تیم توسعه برای اجازه دادن به پذیرش افزایشی، یک گزینه پیکربندی route experimental_ppr را برای انتخاب Layouts و Pages ویژه در PPR اضافه کرده است:

import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
       <StaticComponent />
       <Suspense fallback={...}>
         <DynamicComponent />
       </Suspense>
     </>
  };
}

برای استفاده از گزینه جدید، باید پیکربندی experimental.ppr را در فایل next.config.js خود روی 'incremental' تنظیم نماییم:

const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
};
 
module.exports = nextConfig;

هنگامی که همه بخش‌ها PPR را فعال کردیم، بهتر است که مقدار ppr را روی true تنظیم کنیم و آن را برای کل برنامه و همه مسیرهای آینده فعال نماییم.

اجرای کد پس از response با استفاده از next/after

هنگام پردازش درخواست کاربر، سرور معمولاً وظایفی را انجام می‌دهد که مستقیماً با محاسبه response مرتبط است. با این حال، ممکن است نیاز به انجام کارهایی مانند ورود به سیستم، تجزیه و تحلیل و سایر همگام‌سازی‌های سیستم خارجی داشته باشیم.

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

after() یک API آزمایشی جدید است که این مشکل را حل می‌کند و به ما این امکان را می‌دهد تا پس از اتمام جریان response، کار را برای پردازش ادامه دهیم و تسک‌های ثانویه را قادر می‌سازد تا بدون این که response اولیه را مسدود کنند، اجرا شده و به کار خود ادامه دهند.

برای استفاده از آن، experimental.after را به next.config.js اضافه می‌کنیم:

const nextConfig = {
  experimental: {
    after: true,
  },
};
 
module.exports = nextConfig;

سپس، تابع را در سرور کامپوننت‌ها، سرور اکشن‌ها، Route Handlerها یا Middleware وارد می‌کنیم.

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

بررسی به‌روزرسانی‌های create-next-app

در نسخه ۱۵ Next.js، برنامه create-next-app با طراحی جدید به‌روزرسانی شده است.

هنگام اجرای برنامه create-next-app، یک درخواست جدید وجود دارد که از ما می‌پرسد آیا می‌خواهیم Turbopack را برای توسعه لوکال فعال کنیم یا خیر، که به‌طور پیش‌فرض بر روی No تنظیم شده است.

✔ Would you like to use Turbopack for next dev? … No / Yes

flag --turbo می‌تواند برای فعال کردن Turbopack استفاده شود.

npx create-next-app@rc --turbo

همینطور برای آسان‌تر کردن شروع پروژه جدید، یک flag --empty جدید به CLI اضافه شده است. با استفاده از این flag، هر گونه فایل و استایل اضافی حذف شده و در نهایت یک صفحه «hello world» ساخته می‌شود.

npx create-next-app@rc --empty

بررسی بهینه‌سازی bundling پکیج‌های اکسترنال

Bundling پکیج‌های اکسترنال می‌تواند عملکرد شروع برنامه ما را بهبود بخشد. در App Router، پکیج‌های اکسترنال به‌طور پیش‌فرض bundle می‌شوند، که ما می‌توانیم با استفاده از گزینه جدید پیکربندی serverExternalPackages، از ایجاد bundleهای خاصی صرف نظر کنیم.

در Pages Router، پکیج‌های اکسترنال به‌طور پیش‌فرض bundle نمی‌شوند، اما می‌توانیم با استفاده از گزینه transpilePackages موجود، لیستی از پکیج‌ها را برای bundle شدن ارائه دهیم. با استفاده از این گزینه پیکربندی باید هر پکیج را مشخص نماییم.

برای یکسان‌سازی پیکربندی بین App Router و Pages Router، تیم توسعه یک گزینه جدید به نام bundlePagesRouterDependencies را معرفی می‌کند تا با bundling خودکار پیش‌فرض App Router مطابقت داشته باشد. سپس می‌توانیم برای صرف نظر از پکیج‌های خاص، در صورت نیاز از serverExternalPackages استفاده نماییم.

const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
module.exports = nextConfig;

 

دیدگاه‌ها:

افزودن دیدگاه جدید