Codoloper

فریمورک

Next.js 16.3 Turbopack: وقتی dev server دیگه ۲۱ گیگ رم نمی‌خوره نوشته شده توسط عرفان دهقانی

Next.js 16.3 Turbopack: وقتی dev server دیگه ۲۱ گیگ رم نمی‌خوره

اگه روی یه پروژه‌ی Next.js بزرگ کار کردی و یه نقطه‌ای رسیدی که Task Manager رو باز کردی و دیدی dev server تنهایی داره ۸ گیگ رم می‌خوره، می‌دونی این احساس چیه. Turbopack از اول با این طراحی اومد که همه‌چیز رو cache کنه تا compile سریع‌تر باشه — ولی قیمتش این بود که هرچقدر بیشتر توی پروژه می‌چرخیدی، حافظه بیشتری می‌خورد و هیچ‌وقت هم آزاد نمی‌کرد.

نسخه‌ی ۱۶.۳ این trade-off رو عوض کرده.

مصرف حافظه: ۹۰ درصد کمتر

تیم Turbopack سه ماه روی این کار کرد. نتیجه چیه؟ روی codebase داشبورد vercel.com، بعد از compile کردن ۵۰ route، مصرف حافظه از ۲۱.۵ گیگابایت به ۲ گیگابایت رسیده — یعنی ۹۰ درصد کمتر. روی سایت nextjs.org هم از ۴۶۰۰ مگابایت به ۸۴۰ مگابایت، یعنی حدود ۸۲ درصد کاهش.

چطور؟ با یه مکانیزم جدید به اسم memory eviction. ایده ساده‌ست: به‌جای اینکه نتایج cache شده برای همیشه توی RAM نگه داشته بشن، حالا Turbopack می‌تونه اونایی که دیگه فعال استفاده نمی‌شن رو بریزه روی دیسک و از حافظه پاک کنه. این feature روی filesystem cache که از نسخه‌ی ۱۶.۱ اضافه شده بود تکیه می‌کنه، و توی ۱۶.۳ هر دو به‌صورت پیش‌فرض فعال هستن.

اگه بخوای غیرفعالش کنی یا رفتارش رو debug کنی:

const nextConfig = {
  experimental: {
    turbopackMemoryEviction: false,
  },
};

یه چیز مهم: عدد دقیق کاهش حافظه برای هر پروژه فرق می‌کنه. بستگی داره به اینکه route graph پروژه‌ات چقدر بزرگه و توی یه session چقدر ازش استفاده کردی.

filesystem cache برای build

تا الان، filesystem cache فقط توی next dev کار می‌کرد. از ۱۶.۳، همین cache برای next build هم در دسترسه.

اعداد رو ببین: روی nextjs.org، build با cache از ۲۱ ثانیه به ۹.۲ ثانیه رسیده — ۲.۳ برابر سریع‌تر. روی vercel.com/geist که یه design system بزرگه، از ۳۰ ثانیه به ۵.۵ ثانیه — یعنی ۵.۵ برابر. روی vercel.com/home که پروژه‌ی سنگین‌تریه، بهبود کمتره: از ۶۶ به ۴۶ ثانیه.

فعال کردنش یه flag می‌خواد:

const nextConfig = {
  experimental: {
    turbopackFileSystemCacheForBuild: true,
  },
};

برای CI هم می‌شه از این استفاده کرد: کافیه پوشه‌ی .next رو بین runها کش کنی. وقتی Turbopack اون دایرکتوری رو اول build پیدا کنه، از کار قبلی استفاده می‌کنه به‌جای اینکه همه‌چیز رو از صفر compile کنه.

React Compiler با Rust

React Compiler از نسخه‌ی ۱۶.۰ توی Next.js stable بوده، ولی تا الان فقط به‌عنوان یه Babel transform اجرا می‌شد. مشکل اینجا بود که Babel روی پروژه‌های بزرگ سنگین می‌شد و build رو کند می‌کرد.

تیم React یه پورت native از این compiler با Rust نوشته، و تیم Turbopack سریع این رو integrate کرده. نتایج اولیه روی پروژه‌هایی مثل v0 نشون می‌ده که compile time بین ۲۰ تا ۵۰ درصد بهتر می‌شه. فعلاً experimental هست:

const nextConfig = {
  reactCompiler: true,
  experimental: {
    turbopackRustReactCompiler: true,
  },
};

import.meta.glob

Turbopack حالا از API ای که Vite معروفش کرده پشتیبانی می‌کنه:

const posts = import.meta.glob('./posts/*.mdx');

این به‌جای اینکه مجبور بشی اسم همه‌ی فایل‌ها رو hardcode کنی، هر فایلی که با pattern مطابقت داشته باشه رو import می‌کنه. نتیجه یه object هست که key‌هاش path فایل‌هاست:

for (const path in posts) {
  const post = await posts[path]();
}

می‌تونی با eager: true همه‌شون رو بلافاصله import کنی، یا فقط چند export خاص رو بگیری، یا pattern‌های منفی بگذاری. file watcher هم بهش وصله — اگه فایلی اضافه یا حذف شد، خودش recompile می‌کنه.

یه نکته: این feature فقط روی Turbopack کار می‌کنه. اگه هنوز با --webpack build می‌گیری، اینجا نیست.

HMR سریع‌تر و runtime کوچیک‌تر

دو بهبود دیگه که کمتر headline می‌گیرن ولی در عمل احساس می‌شن: اول اینکه HMR subscription tracking بهتر شده — با یکی کردن چند subscription در جاهایی که قبلاً جداگانه بودن، dev server cold start روی اپ‌های پیچیده بیش از ۱۵ درصد سریع‌تر شده. دوم اینکه runtime code ای که Turbopack به هر route اضافه می‌کنه کوچیک‌تر شده — چون حالا فقط کدی که واقعاً استفاده می‌شه (مثل WebAssembly loader یا worker support) شیپ می‌شه، نه همه‌چیز یکجا.

یه feature کوچیک‌تر هم برای monorepoها اومده: با turbopackLocalPostcssConfig: true می‌تونی per-package پیکربندی PostCSS داشته باشی به‌جای اینکه همه از root config بخوننن.

اگه الان روی Next.js 16.x هستی، این آپدیت شاید مهم‌ترین چیزیه که از نظر DX روزانه حسش می‌کنی — نه یه feature جدید، بلکه اینکه وقتی ساعت‌ها روی پروژه کار می‌کنی، IDE و dev server با هم دیگه دعوا نمی‌کنن سر رم.

Next.js 16.3: AI Improvements وقتی فریمورک برای ایجنت ها طراحی می شه نوشته شده توسط عرفان دهقانی

Next.js 16.3: AI Improvements وقتی فریمورک برای ایجنت ها طراحی می شه

یه چیز جالب داره توی فضای توسعه نرم‌افزار اتفاق می‌افته: یه بخش قابل‌توجه از کدی که توی Next.js نوشته می‌شه دیگه توسط انسان‌ها تایپ نمی‌شه. Claude Code، Cursor، Codex — این‌ها دارن به ابزارهای اصلی خیلی از تیم‌ها تبدیل می‌شن. تیم Next.js یه سوال جالب پرسیده: اگه فریم‌ورک می‌دونست که اکثر کدش رو یه agent می‌نویسه، چی فرق می‌کرد؟

۲۶ ژوئن ۲۰۲۶، Next.js 16.3 یه پست مجزا فقط برای بهبودهای AI-محور منتشر کرد — چیزی که قبلاً سابقه نداشت. این مقاله رو مرور می‌کنه.

AGENTS.md: agent بخونه، نه training data رو

توی نسخه‌ی ۱۶.۲، Next.js شروع کرد به bundled کردن مستنداتش داخل پروژه. ایده ساده بود: agent‌ها اغلب از training data خودشون استفاده می‌کنن، که ممکنه چند نسخه عقب‌تر باشه. اگه داک‌های نسخه‌ی فعلی رو داخل node_modules بگذاری و از طریق AGENTS.md بهش اشاره کنی، agent مجبور می‌شه نسخه‌ی درست رو بخونه.

توی ۱۶.۳، next dev به‌طور خودکار این pointer رو می‌نویسه و به‌روز نگه می‌داره. پروژه‌های قدیمی‌تر می‌تونن با یه codemod یه‌بار این کار رو بکنن:

npx @next/codemod@canary agents-md

بلوکی که next dev به AGENTS.md اضافه می‌کنه صریحه:

<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure
may all differ from your training data. Read the relevant guide in
`node_modules/next/dist/docs/` before writing any code.
<!-- END:nextjs-agent-rules -->

این بلوک فقط وقتی next dev یه AI coding agent رو توی environment تشخیص بده نوشته می‌شه، و هر چیزی بیرون از marker‌ها دست‌نخورده می‌مونه.

Skills: وقتی داک کافی نیست

Skills برای workflow‌های چندمرحله‌ای‌اند — جایی که داک‌ها تنها نمی‌تونن agent رو از اول تا آخر هدایت کنن. سه Skill جدید اضافه شده:

next-dev-loop: به agent دسترسی به dev loop کامل می‌ده — مرورگر، console، network، و درخت React. بعد از هر ویرایش می‌تونه ببینه صفحه هنوز کار می‌کنه یا نه.

npx skills add vercel/next.js --skill next-dev-loop

next-cache-components-adoption: Cache Components رو توی پروژه فعال می‌کنه و یه feature در یه زمان پیش می‌ره. دو mode داره: incremental که یه PR مکانیکی می‌سازه و بقیه رو می‌ذاره برای بعد، و direct که همه‌ی route‌ها رو یه‌جا روی یه branch تغییر می‌ده.

next-cache-components-optimizer: یه route رو برای instant navigation بهینه می‌کنه با یه حلقه‌ی observe-fix-iterate روی static shell. قبل و بعد از هر تغییر screenshot می‌گیره؛ اگه تصاویر یکسان باشن، تغییر rollback می‌شه.

Agent Browser با React introspection

next-browser که توی ۱۶.۲ اضافه شده بود حالا merge شده توی agent-browser — یه CLI همه‌منظوره که فراتر از Next.js هم کار می‌کنه.

نسخه‌ی ۰.۲۷ یه چیز مهم اضافه کرده: React DevTools introspection. Agent‌ها الان می‌تونن درخت کامپوننت رو لیست کنن، یه کامپوننت خاص رو inspect کنن، re-renderها رو profile کنن، و ببینن چی یه render رو نگه داشته.

Actionable errors: خطا با دستورالعمل

وقتی Cache Components فعاله، یه await روی سرور یه انتخابه. Instant Insights این انتخاب رو به‌عنوان یه error با سه fix مشخص نشون می‌ده: Stream با <Suspense>، Cache با "use cache"، یا Block با export const instant = false.

اما مهم‌تر از خود error، یه دکمه‌ی «Copy prompt» اضافه شده. این دکمه fix انتخاب‌شده رو بسته‌بندی می‌کنه توی یه پرامپت آماده برای agent: شناسایی کد مشکل‌دار، خوندن داک مربوط، اعمال pattern، و تایید نتیجه توی مرورگر از طریق next-dev-loop.

همین fix menu توی terminal هم هست. next build و next dev هر دو خطاها رو با گزینه‌های labeled و لینک به بخش مربوطه از داک‌ها output می‌کنن — یعنی agent‌هایی که dev overlay ندارن و فقط terminal رو می‌خونن همون اطلاعات رو می‌گیرن.

هر error یه صفحه‌ی مجزا روی nextjs.org/docs/messages داره که برای خوندن توسط agent‌ها نوشته شده. هر صفحه همون ساختار رو داره: Patterns، Trade-offs، و Gotchas — یه چیزی که agent‌ها توی اولین تلاش احتمالاً بهش توجه نمی‌کنن.

MCP server: کوچیک‌تر و متمرکزتر

MCP server قبلاً یه knowledge base داخلی داشت. با اینکه bundled docs الان همون کار رو می‌کنه، اون ابزارها حذف شدن. در عوض، دو ابزار جدید اضافه شده: get_compilation_issues برای کل پروژه، و compile_route برای یه route خاص. agent‌ها اغلب next build می‌زدن فقط برای چک کردن compilation — این ابزارها همون سوال رو از dev server در حال اجرا جواب می‌دن، خیلی سریع‌تر.

Docs as Markdown

یه چیز ساده ولی کاربردی: به هر URL از داک‌های Next.js یه .md اضافه کن تا نسخه‌ی Markdown صفحه رو بگیری. همین برای صفحه‌های error هم کار می‌کنه.

ایندکس کامل روی /docs/llms.txt هست، و /docs/llms-full.txt همه‌ی صفحات رو توی یه فایل bundle می‌کنه — طبق convention استاندارد llms.txt.

یه قدم به سمت agent-first development

اگه بخوای خیلی ساده بگی چی اضافه شده: Next.js داره سعی می‌کنه agent‌ها رو مثل یه نوع developer جدید در نظر بگیره — با نیازهای متفاوت. Agent به داک‌های به‌روز نیاز داره نه training data قدیمی، به خطاهای actionable نیاز داره نه فقط error message، و به یه feedback loop نیاز داره که بتونه بعد از هر تغییر runtime رو چک کنه.

فعلاً هنوز preview هست. اگه می‌خوای همین الان امتحان کنی:

npm install next@preview

و بعد ببین کدوم بخش از workflow توسعه‌ات واقعاً بهتر می‌شه — یا نمی‌شه.

Next.js 16.3: وقتی اپ سرور-محورت مثل SPA رفتار می‌کنه نوشته شده توسط عرفان دهقانی

Next.js 16.3: وقتی اپ سرور-محورت مثل SPA رفتار می‌کنه

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

در حالی که SPAها از روز اول همین مشکل رو حل کرده بودن: کلیک می‌کنی، یه shell از صفحه‌ی بعدی بلافاصله نشون داده می‌شه — حتی اگه داده‌ها هنوز دارن لود می‌شن. این حس «instant» بودن چیزیه که خیلی از توسعه‌دهنده‌ها رو به سمت SPAها می‌کشه، حتی وقتی می‌دونن که مدل سرور-محور Next.js از نظر فنی برتری‌های زیادی داره.

۲۵ ژوئن ۲۰۲۶، تیم Next.js یه پیش‌نمایش از نسخه‌ی ۱۶.۳ منتشر کرد که مستقیماً همین مشکل رو هدف گرفته: Instant Navigations.

ایده‌ی اصلی چیه

وقتی یه route توی Next.js به داده‌ای از سرور await می‌کنه، سه گزینه داری:

Stream با <Suspense>: کاربر بلافاصله یه loading shell می‌بینه و داده‌ها بعداً stream می‌شن. navigation ایمدیت، داده‌ها دیرتر.

Cache با 'use cache': کاربر یه UI کش‌شده‌ی قبلی رو می‌بینه، تا زمانی که نسخه‌ی جدید آماده بشه. باز هم navigation ایمدیت.

Block با export const instant = false: بگی این route نباید instant باشه — مثلاً یه بلاگ که نمی‌خوای shell خالی صفحه‌ی پست رو نشون بده. navigation منتظر سرور می‌مونه.

دو گزینه‌ی اول navigation رو به حالت SPA-like در میارن. گزینه‌ی سوم اختیارى‌ه و بهت کنترل می‌ده.

برای فعال کردنش، یه flag توی next.config.ts اضافه می‌کنی:

const nextConfig: NextConfig = {
  cacheComponents: true,
};

این flag قراره در یه major version آینده به حالت default تبدیل بشه.

prefetching رو هم از اول طراحی کردن

یه مشکل دیگه هم وجود داشت که کمتر بهش توجه می‌شد: حتی اگه سرور سریع جواب بده، هنوز یه رفت‌وبرگشت شبکه بین client و سرور داری. Next.js قبلاً این مشکل رو با prefetch کردن لینک‌ها حل می‌کرد — برای هر لینکی که توی viewport بود، یه request جداگانه می‌زد. اگه یه sidebar با بیست لینک داشتی، بیست request. اگه به Network tab نگاه می‌کردی، یه طوفان از request‌ها می‌دیدی که به گفته‌ی خود تیم Next.js «مسخره به نظر می‌رسید».

توی ۱۶.۳ این رویکرد عوض شده: به جای prefetch کردن به‌ازای هر لینک، حالا یه shell به‌ازای هر route prefetch می‌شه. یعنی اگه بیست لینک داری که همه به /chat/[id] اشاره می‌کنن، فقط یه بار shell اون route دانلود می‌شه و کش می‌شه.

برای فعال کردن این رفتار:

const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
};

البته اگه بخوای برای یه لینک خاص بیشتر از shell prefetch بشه — مثلاً header یه صفحه‌ی chat — می‌تونی با <Link prefetch={true}> opt-in کنی. توی اون حالت هم Next.js فقط تا جایی prefetch می‌کنه که synchronous یا 'use cache' باشه، نه کل route.

Instant Insights: slow navigation به‌عنوان error

چیزی که توی این آپدیت جالبه اینه که تیم Next.js تصمیم گرفته navigation‌های کند رو توی development mode به‌عنوان error نشون بده — نه warning، error. یه پنل جدید به اسم Instant Insights اضافه شده که به‌طور خودکار route‌هایی که instant نیستن رو پیدا می‌کنه و نشون می‌ده.

برای تست هم یه helper اضافه شده:

import { instant } from '@next/playwright';

test('navigation is instant', async ({ page }) => {
  await page.goto('/products/shoes');
  await instant(page, async () => {
    await page.click('a[href="/products/hats"]');
    await expect(page.locator('h1')).toContainText('Baseball Cap');
    await expect(page.getByText('Checking inventory...')).toBeVisible();
  });
});

این یعنی می‌تونی توی CI هم چک کنی که navigation‌های instant بودنشون رو از دست ندادن.

یه Navigation Inspector هم اضافه شده که بهت اجازه می‌ده هر navigation رو «pause» کنی و ببینی shell چه شکلیه، قبل از اینکه داده‌های واقعی بیان.

چقدر واقعاً فرق می‌کنه

تیم Next.js گفته که این feature رو روی v0 — اپ داخلی Vercel — قبل از release استفاده کردن. نتیجه‌ای که منتشر کردن نشون می‌ده که navigation time از چند صد میلی‌ثانیه به نزدیک صفر رسیده برای اکثر route‌ها، بعد از اینکه کار روی route‌های کند رو تموم کردن.

البته این هنوز preview هست و یه سری محدودیت‌های شناخته‌شده هم وجود داره: بعضی route‌های blocking توی Instant Insights گزارش نمی‌شن، و tooling توی Safari مشکل داره. تیم گفتن که این‌ها قبل از stable release برطرف می‌شن.

چطور امتحانش کنی

npm install next@preview

بعدش cacheComponents: true رو به config اضافه کن و ببین کدوم route‌هات blocking هستن. اگه می‌خوای Partial Prefetching هم باشه، partialPrefetching: true رو هم اضافه کن.

یه دمو هم آماده کردن به اسم Next Beats — یه موزیک‌پلیر که روی Next.js 16.3 ساخته شده و سورسش هم روی GitHub هست — که می‌تونی ببینی navigation‌های instant در عمل چطور به نظر می‌رسن.

این مسیری که Next.js داره طی می‌کنه — گرفتن بهترین چیز SPA (navigation ایمدیت) بدون دادن مزایای server-centric — از نظر فنی جالبه. مشکل اصلی که همیشه بود این بود که مجبور بودی یا همه‌چیز رو client‌ side بکنی تا instant باشه، یا server‌ side بروی و سرعت navigation رو فدا کنی. حالا دیگه این trade‌off اجباری نیست.

تفاوت React Element، JSX Element و React Node چیست؟ نوشته شده توسط Haleh Nakisa

تفاوت React Element، JSX Element و React Node چیست؟

اگر در حال توسعه پروژه‌های ری‌اکت یا نکست‌جی‌اس با TypeScript هستید، قطعا موقع نوشتن کامپوننت‌ها یا تعریف تمپلیت‌ها، به این سه تایپ (Type) برخوردید: ReactNode ،ReactElement و JSX.Element.

در این مقاله می‌خوایم به زبون ساده و با مثال‌های واقعی بررسی کنیم که این سه مفهوم دقیقاً چی هستن، چه تفاوتی با هم دارن و در چه سناریویی باید از کدومشون استفاده کنیم.
۱. مفهوم React Element:
یک React Element کوچک‌ترین واحد سازنده در یک اپلیکیشن ری‌اکت هستش. از نظر فنی، این تایپ یک شیء (Object) ساده و جاوااسکریپتیه که توصیف می‌کنه یک جزء از پورتال یا UI شما چطور باید به نظر برسه (مثلاً نوعش چیه، چه Propsهایی داره و فرزندانش کدوم هستن).
وقتی شما یک کامپوننت یا تگ HTML رو می‌نویسین، ری‌اکت در پشت صحنه اون رو به یک الگو تبدیل می‌کنه.
چه زمانی تولید می‌شه؟ هر زمانی که تابع React.createElement() فراخوانی شه.
ویژگی مهم: این تایپ نمی‌تونه شامل متن ساده (String)، عدد یا آرایه باشه؛ بلکه فقط و فقط یک آبجکت معتبر ری‌آکتیه.

// این یک ReactElement است
const element: React.ReactElement = <h1>سلام کادولوپر!</h1>; 

// این خطا ایجاد می‌کند چون رشته متنی به تنهایی ReactElement نیست
const invalidElement: React.ReactElement = "Hello World"; // Error!
۲. مفهوم JSX.Element:
JSX.Element و React Element: این دو تقریباً یک چیز هستن! در واقع JSX.Element یک متغیر سراسری (Global) هستش که توسط خود زبان جاوااسکریپت/تایپ‌اسکریپت (درست خارج از هسته ری‌اکت) تعریف میشه تا خروجی سینتکس‌های JSX رو تایپ‌دهی کنه. از نظر ساختاری، JSX.Element چیزی نیست بجز یک اینترفیس که مستقیماً از ReactElement ارث‌بری می‌کنه، اما با این تفاوت که تایپِ فیلدهای props و type اون به صورت پیش‌فرض any در نظر گرفته شده تا منعطف‌تر باشه.
// هر دو خط زیر از نظر عملکردی کاملاً یکسان هستند:
const buttonOne: React.ReactElement = <button>کلیک کنید</button>;
const buttonTwo: JSX.Element = <button>کلیک کنید</button>;
۳. مفهوم React Node:
می‌رسیم به بزرگ‌ترین تایپ در ری‌آکت: React Node.
تایپ ReactNode در واقع یک ابرمجموعه (Superset) هستش؛ یعنی هر چیزی که ری‌آکت توانایی رندر کردن اون رو روی صفحه داشته باشه، زیرمجموعه ReactNode قرار می‌گیره. به تعریف تایپ اون در هسته ری‌آکت نگاه کنید:
type ReactNode = ReactElement | string | number | Iterable<ReactNode> | ReactPortal | boolean | null | undefined;
همون‌طور که می‌بینید، یک ReactNode می‌تونه یک آبجکت ری‌اکتی، یک متن ساده، یک عدد، آرایه‌ای از المان‌ها، یا حتی مقادیر خالی مثل null و undefined باشه.
// تمام موارد زیر به عنوان ReactNode کاملاً معتبر هستند:
const nodeText: React.ReactNode = "یک متن ساده";
const nodeNumber: React.ReactNode = 1405;
const nodeElement: React.ReactNode = <div>یک المان کامپوننت</div>;
const nodeNull: React.ReactNode = null;
کجا از کدوم استفاده کنیم؟
الان که با ماهیت هرکدوم آشنا شدیم، بیاید ببینیم در پروژه‌های واقعی (مخصوصا موقع تعریف ابزارهای کاستوم و پروژه‌های تیمی) بهترین انتخاب کدوم میشه.
سناریوی اول: تعریف فیلد children در کامپوننت‌ها (Best Practice: ReactNode)
اگر در حال ساخت یک کامپوننتِ Wrapper مثل دکمه‌های عمومی، Layout اصلی سایت یا کامپوننت‌های Card هستید که قراره محتوای مختلفی درون خودش جا بده، همیشه از ReactNode استفاده کنید. این کار به بقیه برنامه‌نویسها اجازه میده تا هر چیزی (از متن ساده تا چند تگ تو در تو) رو داخل کامپوننت شما بفرستند:
type LayoutProps = {
  children: React.ReactNode; // بهترین انتخاب برای دریافت هر نوع محتوا
};

export default function Layout({ children }: LayoutProps) {
  return <main className="main-container">{children}</main>;
}
سناریوی دوم: محدود کردن خروجی به تگ‌های ساختاریافته (Best Practice: ReactElement)
تصور کنید در حال ساخت کامپوننتی به نام List هستید و می‌خواید کاربر فقط و فقط تگ‌های <ListItem /> رو به عنوان فرزند ارسال کنه و اجازه نداشته باشه رشته متنی ساده یا عدد خالی بفرسته. در این سناریو، ReactElement انتخاب بهتری هست:
type ListProps = {
  // کاربر نمی‌تواند متن ساده بفرستد، حتماً باید یک کامپوننت یا تگ معتبر باشد
  children: React.ReactElement; 
};
سناریوی سوم: تایپ‌دهی خروجی توابع یا هوک‌های کاستوم (Best Practice: JSX.Element)
اگر متدی نوشتید که وظیفه‌ش تولید و برگردوندن یک قطعه کد HTML یا کامپوننت هستش، تعیین JSX.Element به عنوان تایپ خروجی، خوانایی کد شما رو بالا می‌بره و مشخص می‌کنه که خروجی این تابع یک سینتکس JSX هستش:
const renderStatusIcon = (status: string): JSX.Element => {
  if (status === "success") return <SuccessIcon />;
  return <ErrorIcon />;
};
جمع‌بندی
انتخاب درست بین این سه تایپ، بستگی به میزان سخت‌گیری یا انعطاف‌پذیری لازم در کدهای شما داره. اگر دنبال انعطاف زیاد برای رندر انواع داده‌ها باشید، ReactNode انتخاب خوبیه. اما اگر می‌خواید ساختار رو محدود به آبجکت‌های معتبر طراحی UI کنید، ReactElement و JSX.Element بهترین گزینه‌ها هستن.
شما در پروژه‌های خودتون بیشتر با کدوم‌ از این تایپ‌ها سر و کار دارید؟ تا حالا به خاطر استفاده جابجا از اون‌ها به باگ‌های تایپ‌اسکریپتی خوردید؟ تجربیات خودتون رو در بخش نظرات با ما در میون بذارید!
چطور خطای Unknown at rule را در VS Code برطرف کنیم؟ نوشته شده توسط Haleh Nakisa

چطور خطای Unknown at rule را در VS Code برطرف کنیم؟

اگر تو پروژه‌هاتون از فریم‌ورک‌های مدرن CSS مثل Tailwind CSS استفاده می‌کنید، احتمالاً این هشدار رو دیدید: وقتی میخواید از دایرکتیوهایی مثل @apply، @theme یا @tailwind، استفاده کنید ویرایشگر VS Code زیر اونهاخط زرد یا قرمز می‌کشه و خطای Unknown at rule css(unknownAtRules) رو نمایش میده.
این اتفاق به این دلیل میفته که لینتر (Linter) پیش‌فرض VS Code، دایرکتیوهای اختصاصی فریم‌ورک‌ها رو به عنوان کدهای استاندارد CSS نمی‌شناسه. اگرچه این هشدار هیچ اختلالی تو کامپایل و اجرای پروژه ایجاد نمی‌کنه، اما در فایل‌های استایل، ظاهر کدها رو آشفته می‌کنه و تمرکز توسعه‌دهنده رو به هم می‌زنه.
در این آموزش کوتاه، یاد می‌گیریم چطوری تو کمتر از یک دقیقه این مشکل رو برای همیشه تو ادیتورمون برطرف کنیم.
اگر از فایل‌های استاندارد .css استفاده می‌کنید
برای غیرفعال کردن این هشدار و نادیده گرفتن دایرکتیوهای ناشناخته توسط VS Code، این مرحله‌ها رو دنبال کنید:
۱. کلیدهای ترکیبی Ctrl + Shift + P (در مک Cmd + Shift + P) رو فشار بدید تا منوی دستوراهای (Command Palette) باز شه.
۲. عبارت settings.json رو تایپ کنید. بین گزینه‌های پیشنهادی، معمولاً سه فایل زیر رو می‌بینید:
Open User Settings (JSON)
Open Default Settings (JSON)
Open Workspace Settings (JSON)
۳. گزینه اول(ممکنه برای شما گزینه اول نباشه)، Open User Settings (JSON) رو انتخاب کنید تا فایل تنظیمات کاربریتون باز شه.
۴. خط کد زیر رو به انتهای این فایل (قبل از بستن آکاردئون اصلی {}) اضافه کنید:

"css.lint.unknownAtRules": "ignore"
۵. فایل رو با کلیدهای Ctrl + S (در مک Cmd + S) ذخیره کنید. بلافاصله بعد از ذخیره، همه هشدارهای مربوط به این بخش ناپدید میشن.
اگر از فایل‌های .scss استفاده می‌کنید
اگر تو پروژهاتون در کنار فریم‌ورک‌هایی مثل تیلوند، از پیش‌پردازنده‌ی ساس (Sass) استفاده می‌کنید و پسوند فایل‌های استایل شما .scss هستش، باید تنظیمات مربوط به این فرمت رو تغییر بدید. به جای کد قبل، کافیه کد زیر رو به همون فایل settings.json اضافه کنید:
"scss.lint.unknownAtRules": "ignore"
نکته: اگر تو پروژه‌های مختلفتون هم از CSS معمولی و هم از SCSS استفاده می‌کنید، می‌تونید هر دو خط کد رو در فایل تنظیمات قرار بدید تا این خطا تو هیچ‌کدوم از فایل‌ها تکرار نشه.

جمع‌بندی
گاهی اوقات هشدارهای پیش‌فرضِ ابزارهای توسعه، برای کدهای مدرن بهینه‌سازی نشدن و باعث شلوغی محیط کدنویسی می‌شن. با انجام این تغییر ساده، ادیتورتون رو جوری شخصی‌سازی کردید که تنها خطاهای واقعی و ساختاری کد رو به شما نشون میده.
شما برای حل این مشکل از چه روشی استفاده می‌کردید؟
دیپلوی حرفه‌ای NextJs روی VPS با Docker نوشته شده توسط عرفان دهقانی

دیپلوی حرفه‌ای NextJs روی VPS با Docker

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

اینجاست که Docker وارد میشه.

داکر به شما اجازه میده کل محیط اجرای اپلیکیشن رو داخل یک کانتینر بسته‌بندی کنید؛ یعنی نسخه Node.js، پکیج‌ها، تنظیمات و هر چیزی که پروژه برای اجرا نیاز داره. نتیجه اینه که برنامه دقیقاً به همون شکلی که روی سیستم شما کار می‌کنه، روی سرور هم اجرا میشه. فرقی نداره سرور Ubuntu باشه یا Debian، VPS داخل ایران باشه یا خارج از کشور.

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

در این آموزش از نصب Docker روی سرور شروع می‌کنیم، پروژه Next.js یا Node.js رو کانتینری می‌کنیم، با Docker Compose اجراش می‌کنیم و در نهایت با Nginx و SSL اون رو برای استفاده در محیط Production آماده می‌کنیم.

میتونی قبل شروع این مقاله هارو بخونی که کمکت کنه بهتر متوجه اینجا بشی و همچنین یجورایی پیشنیاز هستن:

  1. داکر چیست و چرا ازش استفاده کنیم
  2. لینوکس چیست (معمولا سیستم عامل vps ها لینوکس هست)
  3. SSH چیست (اتصال به سرور از سیستم شخصی)
  4. کامند های ترمینال لینوکس (شاید بخواید یاد بگیرید، خیلی کارا میشه باهاشون کرد)

۱. نصب Docker روی VPS

آپدیت سیستم:

apt update && apt upgrade -y

نصب Docker:

curl -fsSL https://get.docker.com | sh

فعال‌سازی و بررسی:

systemctl enable docker
systemctl start docker
docker -v
کامند اول سرویس داکر رو فعال میکنه، بعدی اجراش میکنه و سومی هم ورژن داکر رو بهتون نشون میده که اگر نشون داد یعنی اوکیه همه چیز تا اینجا.

۲. نصب Docker Compose

apt install docker-compose-plugin -y
docker compose version

بعد از نصب داکر کامپوز ورژنش رو چک کنید که اون هم اوکی باشه


۳. میرورهای داخلی — ویژه کاربران ایران

به دلیل قطعی‌های مکرر اینترنت بین‌الملل در ایران، دانلود مستقیم از Docker Hub اغلب ناموفقه. استفاده از میرور داخلی یک ضرورته، نه یک پیشنهاد اختیاری.

DevNeeds

یکی از کامل‌ترین میرورهای داخلی ایران. پوشش میده:

  • Docker Hub
  • پکیج منیجرهای زبان‌های مختلف (npm، pip، composer، cargo و ...)
  • نسخه‌های مختلف PostgreSQL

ArvanCloud

زیرساخت ابری ایرانی با میرور برای:

فعال کردن میرور Docker

فایل تنظیمات daemon رو ویرایش کن:

nano /etc/docker/daemon.json

محتوای زیر رو وارد کن:

{
  "registry-mirrors": [
    "https://mirror.devneeds.ir",
    "https://docker.arvancloud.ir"
  ]
}

بعد از ذخیره، Docker رو ری‌استارت کن:

systemctl daemon-reload
systemctl restart docker
docker info | grep -A5 "Registry Mirrors"

برای میرور سیستم‌عامل، بالا لینک کردم دقیقا کجا باید برید — آدرس دقیق sources.list برای هر distro اونجاست.


۴. آماده‌سازی پروژه Node.js

ساختار استاندارد:

app/
├── src/
│   └── index.js
├── package.json
├── package-lock.json
├── Dockerfile
└── docker-compose.yml

۵. ساخت Dockerfile

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm ci

COPY . .

RUN npm run build

EXPOSE 3000

CMD ["npm", "start"]

اینجا حواستون باشه نوع بیلدتون چیه توی Next Js، مثلا اگر standalone باشه باید از "node /server.js" برای شروع سرو کردن استفاده کنید:

FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .

RUN npm run build

FROM node:20-alpine

WORKDIR /app

COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

EXPOSE 3000

CMD ["node", "server.js"]

دلیل copy کردن package.json قبل از سورس: Docker لایه‌ها رو cache می‌کنه. اگر سورس کد عوض بشه ولی dependency عوض نشه، npm install مجدداً اجرا نمیشه و build سریع‌تره.


۶. ساخت docker-compose.yml

version: "3.8"

services:
  app:
    build: .
    container_name: node_app
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    deploy:
      resources:
        limits:
          memory: 512M

۷. اجرا و دیپلوی

اجرای اولیه:

docker compose up -d --build

بررسی وضعیت و لاگ:

docker ps
docker logs -f node_app

آپدیت بعد از هر بار تغییر کد:

git pull
docker compose up -d --build

این یعنی: بدون نیاز به نصب Node روی سرور، بدون conflict dependency، بدون خراب شدن محیط.


۸. Nginx به عنوان Reverse Proxy

نصب:

apt install nginx -y

کانفیگ در /etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

فعال‌سازی:

ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx

۹. SSL رایگان با Let's Encrypt

apt install certbot python3-certbot-nginx -y
certbot --nginx -d your-domain.com

قبل از اجرا مطمئن شو DNS دامنه‌ات به IP سرور اشاره می‌کنه و پورت ۸۰ باز باشه.

همچنین اینجا بازم باید بگم که بخاطر شرایط اینترنت ایران، بهتره که ssl رو هم از روش های جایگذین ست کنید که renew بشه که توی devneeds  (بخش SSL) مثلا توضیح داده شده به صورت رایگان گرفتن ssl.


۱۰. تنظیمات Production

در docker-compose.yml از restart: unless-stopped استفاده کن تا container بعد از ری‌استارت سرور هم بالا بیاد.

برای دیدن لاگ‌های دقیق‌تر:

docker logs -f node_app
docker inspect node_app

جمع‌بندی

ترکیب استاندارد برای یه دیپلوی حرفه‌ای:

  • Docker — اجرای ایزوله اپ
  • Docker Compose — مدیریت سرویس‌ها
  • Nginx — reverse proxy و ورودی ترافیک
  • SSL — امنیت ارتباط
  • میرور داخلی — پایداری در شرایط ایران
روشمشکل اصلی
Node + PM2 مستقیموابستگی به سرور — هر تغییری می‌تونه محیط رو خراب کنه
نصب دستیconflict dependency — قابل تکرار نیست
Docker + Composeمحیط ثابت — deploy یکسان روی همه سرورها
آپدیت 16.2 نکست جی اس منتشر شد - Next js Update نوشته شده توسط عرفان دهقانی

آپدیت 16.2 نکست جی اس منتشر شد - Next js Update

نسخه 16.2 فریمورک Next.js منتشر شد.

این به‌روزرسانی با تمرکز بر بهبود عملکرد، تجربه توسعه‌دهندگان و قابلیت‌های مرتبط با هوش مصنوعی عرضه شده و تغییرات قابل توجهی را به همراه دارد.

مهم‌ترین قابلیت‌های این نسخه:

  • حدود ۴۰۰٪ افزایش سرعت راه‌اندازی محیط توسعه (next dev)
  • حدود ۵۰٪ بهبود سرعت رندرینگ
  • طراحی جدید صفحه پیش‌فرض خطای 500
  • نمایش لاگ اجرای Server Functionها در ترمینال توسعه
  • اضافه شدن Hydration Diff Indicator برای نمایش دقیق تفاوت خروجی سرور و کلاینت هنگام بروز خطا
  • پشتیبانی از فلگ --inspect در next start برای اتصال دیباگر Node.js به سرور Production
  • بهبودهای گسترده در Turbopack و رفع بیش از ۲۰۰ باگ و مشکل گزارش‌شده
  • بهبود قابلیت‌های مرتبط با Agentها و ابزارهای هوش مصنوعی

اگر از Next.js استفاده می‌کنید، این نسخه می‌تواند تجربه توسعه سریع‌تر و بهتری را برای شما فراهم کند.

بروزرسانی به نسخه جدید:

# با ابزار کامند لاین اتومانیک
npx @next/codemod@canary upgrade latest
 
# به صورت دستی
npm install next@latest react@latest react-dom@latest
 
# ساخت پروژه جدید
npx create-next-app@latest

برای مطالعه جدیدترین اخبار، به‌روزرسانی‌ها و قابلیت‌های دنیای برنامه‌نویسی، کدلپر را دنبال کنید.