Next.js 16, कैश कंपोनेंट्स और रिएक्ट कंपाइलर: वास्तव में क्या बदलता है
· 8 min read · Filippo Spinella · Next.js, React, Frontend, Performance
वर्षों से Next.js में सबसे कष्टप्रद प्रश्नों में से एक यह रहा है: "क्या यह पृष्ठ स्थिर या गतिशील है?"। यह एक साधारण प्रश्न प्रतीत होता है, जब तक कि आप cookies() में एक कॉल, विभिन्न विकल्पों के साथ एक fetch, एक डेटाबेस क्लाइंट, एक CMS, एक शॉपिंग कार्ट, या कस्टम सामग्री का एक टुकड़ा नहीं जोड़ते।
Next.js 16 दिलचस्प है क्योंकि यह इस बातचीत को कम रहस्यमय बनाने की कोशिश करता है। यह जटिलता को खत्म नहीं करता है, लेकिन यह मानसिक मॉडल को बदल देता है: मार्ग डिफ़ॉल्ट रूप से गतिशील होते हैं, कैश जहां आवश्यक हो वहां खुद को घोषित करता है, और Suspense ताजा रहने वाले हिस्सों के साथ तेज शेल बनाने का प्राकृतिक तरीका बन जाता है।
समझने की सुविधा कैश कंपोनेंट्स है। स्थिर टर्बोपैक, रिएक्ट कंपाइलर, proxy.ts, और नए अमान्यकरण एपीआई महत्वपूर्ण हैं, लेकिन वे एक ही समस्या के इर्द-गिर्द घूमते हैं: पर्दे के पीछे फ्रेमवर्क ने क्या निर्णय लिया, इसका अनुमान लगाए बिना तेज़ ऐप्स बनाना।
क्योंकि ये बात मायने रखती है
एक वास्तविक ऐप में आपके पास केवल "स्थैतिक पृष्ठ" और "गतिशील पृष्ठ" नहीं होते हैं। आपके पास अलग-अलग ज़रूरतों वाले अलग-अलग टुकड़े हैं।
उत्पाद शीट दिन में कुछ बार बदल सकती है। कीमत अधिक बार बदल सकती है. उपलब्धता लगभग लाइव होनी चाहिए. उपयोक्तानाम व्यक्तिगत है. समीक्षाएं स्ट्रीम की जा सकती हैं. साइडबार स्थिर हो सकता है. गाड़ी नहीं है.
यदि आप हर चीज़ को एक इकाई के रूप में मानते हैं, तो आप हमेशा दो चरम सीमाओं में से एक में पहुँचते हैं:
- आक्रामक कैशिंग और पुराने डेटा को देखने का जोखिम;
- हर जगह गतिशील प्रतिपादन और प्रदर्शन आवश्यकता से अधिक खराब।
कैश कंपोनेंट्स इस गलत विकल्प से बचने के लिए सटीक रूप से कार्य करता है।
व्यवहार में मॉडल
cacheComponents: true के साथ, आप "use cache" का उपयोग करके घोषित कर सकते हैं कि कैश करने योग्य क्या है। फिर आप अवधि और टैग को cacheLife() और cacheTag() के साथ जोड़ सकते हैं। गतिशील हिस्से गतिशील रहते हैं और Suspense से अलग किए जा सकते हैं।
सेटअप छोटा है:
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig;
बड़ा बदलाव कॉन्फ़िगरेशन में नहीं है. यह इस पर निर्भर करता है कि आप घटकों को कैसे लिखना शुरू करते हैं।
// app/products/[slug]/page.tsx import { Suspense } from 'react'; import { cacheLife, cacheTag } from 'next/cache'; async function getProduct(slug: string) { 'use cache'; cacheLife('hours'); cacheTag(`product:${slug}`); return db.product.findUnique({ where: { slug } }); } async function ProductDetails({ slug }: { slug: string }) { const product = await getProduct(slug); return ( <section> <h1>{product.name}</h1> <p>{product.description}</p> </section> ); } async function LiveInventory({ slug }: { slug: string }) { const inventory = await db.inventory.findFirst({ where: { slug } }); return <p>{inventory.quantity} pezzi disponibili</p>; } export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; return ( <> <ProductDetails slug={slug} /> <Suspense fallback={<p>Controllo disponibilità...</p>}> <LiveInventory slug={slug} /> </Suspense> </> ); }
पेज को पूरी तरह से कैश्ड या पूरी तरह से गतिशील होना जरूरी नहीं है। उत्पाद शीट तेज़ और पुन: प्रयोज्य हो सकती है। इन्वेंट्री ताज़ा रह सकती है. उपयोगकर्ता सबसे धीमे हिस्से की प्रतीक्षा किए बिना, तुरंत कुछ देखता है।
use cache निष्पादन योग्य दस्तावेज़ है
मुझे "use cache" के बारे में जो बात पसंद है वह यह है कि यह आपको अपना इरादा स्पष्ट करने के लिए मजबूर करती है। जब आप कोई फ़ंक्शन पढ़ते हैं, तो आप तुरंत समझ जाते हैं कि किसी ने निर्णय लिया है: "इस डेटा का पुन: उपयोग किया जा सकता है"।
यह विशेष रूप से तब उपयोगी होता है जब आप fetch का उपयोग नहीं कर रहे हों। कई ऐप्स प्रिज्मा, ड्रिज़ल, आंतरिक एसडीके, सीएमएस क्लाइंट या सेवा कार्यों से डेटा पढ़ते हैं। उन मामलों में केवल fetch विकल्पों पर आधारित पुराना तर्क पर्याप्त नहीं था।
अंगूठे का एक नियम:
- कैशिया सामग्री अपेक्षाकृत स्थिर;
- दानेदार टैग का उपयोग करें;
- गतिशील अनुमतियाँ, सत्र, कार्ट, सूचनाएँ और लेन-देन संबंधी स्थितियाँ छोड़ता है;
- धीमे भागों को
Suspenseके अंदर रखें; - "हमने प्रदर्शन में सुधार किया" कहने से पहले मापें।
सब कुछ फेंके बिना अमान्य करें
कैश तभी उपयोगी है जब आप इसे सटीक रूप से अपडेट कर सकें। यहां cacheTag, revalidateTag और updateTag महत्वपूर्ण हो जाते हैं।
उदाहरण:
'use server'; import { updateTag } from 'next/cache'; export async function updateProductName(productId: string, name: string) { await db.product.update({ where: { id: productId }, data: { name }, }); updateTag(`product:${productId}`); }
महत्वपूर्ण विवरण टैग है. product:${productId} एक सटीक सीमा बताता है। products एक बड़ी बाल्टी बताता है। सबसे पहले बड़ी बाल्टी आरामदायक होती है; कुछ महीनों के बाद यह कारण बन जाता है कि आप किसी शीर्षक को बदलने के लिए आधे ऐप को अमान्य कर देते हैं।
स्थिर टर्बोपैक: वह हिस्सा जो आप हर दिन सुनते हैं
Next.js 16 विकास और निर्माण के लिए टर्बोपैक को केंद्र में लाता है। यह सबसे काव्यात्मक विशेषता नहीं है, लेकिन यह वह है जिसे आप काम करते समय महसूस करते हैं: सर्वर जो पहले शुरू होता है, तेजी से ताज़ा होता है, ऐसा बनाता है जो एक मजबूर कॉफी ब्रेक की तरह महसूस करना बंद कर देता है।
जैसा कि कहा गया है, मैं अपनी आंखें बंद करके कस्टम प्लगइन्स से भरे कोडबेस को माइग्रेट नहीं करूंगा। मैं जाँच करूँगा:
- स्थानीय निर्माण;
- गैर-मानक आयात;
- एमडीएक्स, एसवीजी और सीएसएस;
- वेबपैक प्लगइन्स बचे;
- महत्वपूर्ण पृष्ठ;
- निर्माण समय में अंतर.
नई परियोजनाओं के लिए, मैं डिफ़ॉल्ट से शुरू करूँगा। परिपक्व लोगों के लिए, मैं एक मापा प्रवासन करूँगा।
रिएक्ट कंपाइलर: शोर हटाएं, विचार नहीं
रिएक्ट कंपाइलर 1.0 स्थिर है और Next.js 16 इसे reactCompiler के साथ सपोर्ट करता है। वादा यह है कि बहुत सारे मैन्युअल संस्मरण को कम किया जाए: कम memo, कम useMemo, कम useCallback का उपयोग "सुरक्षा के लिए"।
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { reactCompiler: true, }; export default nextConfig;
मैं इसे जादुई धूल की तरह नहीं मानूंगा। जब कोड रिएक्ट नियमों का अच्छी तरह से पालन करता है तो कंपाइलर मदद करता है। यदि घटकों में अजीब दुष्प्रभाव, छिपे हुए उत्परिवर्तन या बुरी तरह से उपयोग किए गए हुक हैं, तो पहले इसे ठीक करने की आवश्यकता है।
इसे आज़माने का स्वस्थ तरीका:
- अद्यतन
eslint-plugin-react-hooks; - वास्तविक उल्लंघनों को ठीक करें;
- इसे नियंत्रित क्षेत्र पर सक्षम करें;
- निर्माण समय और व्यवहार को मापें;
- मैन्युअल संस्मरण तभी हटाएँ जब इसकी आवश्यकता न रह जाए।
लक्ष्य प्रत्येक useMemo को मिटाना नहीं है। लक्ष्य निवारक संस्मरण लिखना बंद करना है क्योंकि हम प्रतिपादन से डरते हैं।
proxy.ts और नेटवर्क सीमा
पुराना middleware.ts proxy.ts बन जाता है। यह एक नाम परिवर्तन है, लेकिन यह समझ में आता है: वह फ़ाइल अनुरोध सीमा पर बैठती है, यह पारंपरिक बैकएंड-शैली जेनेरिक मिडलवेयर नहीं है।
// proxy.ts import { NextRequest, NextResponse } from 'next/server'; export default function proxy(request: NextRequest) { const isLoggedIn = Boolean(request.cookies.get('session')); if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); }
यहां नियम सरल है: इसे छोटा रखें। रीडायरेक्ट, ऑथ रूटिंग, हेडर, आवश्यक पुनर्लेखन। यदि यह दूसरे बैकएंड की तरह महसूस होने लगे, तो संभवतः यह बहुत अधिक काम कर रहा है।
मैं वास्तव में कैसे प्रवास करूंगा
मैं सभी सुविधाएं एक साथ चालू नहीं करूंगा. मैं यह करूँगा:
- मैं नेक्स्ट, रिएक्ट और रिएक्ट डोम को अपडेट करता हूं;
- मैं आधिकारिक कोडमॉड लॉन्च करता हूं;
- मैं
params,searchParams,cookies(),headers()औरdraftMode()पर ब्रेकिंग परिवर्तन ठीक करता हूं; - मैं
middleware.tsकोproxy.tsमें स्थानांतरित करता हूँ; - मैं बिल्ड और महत्वपूर्ण पृष्ठों की जाँच करता हूँ;
- मैं उस अनुभाग पर कैश घटकों को सक्षम करता हूं जहां कैश वर्तमान में घर्षण पैदा करता है;
- मैं टैग और अमान्यकरण के लिए सम्मेलनों को परिभाषित करता हूं;
- मैं रिएक्ट कंपाइलर को अलग से आज़माता हूँ;
- पहले और बाद के मेट्रिक्स की तुलना।
अच्छा माइग्रेशन वह नहीं है जो सभी नई सुविधाओं का उपयोग करता है। यह ऐप के व्यवहार को अधिक पठनीय बनाता है।
सोचने के तरीके में क्या बदलाव आता है
Next.js 16 के बारे में सबसे उपयोगी बात यह है कि यह आपको इरादों को बेहतर नाम देने के लिए मजबूर करता है। एक फ़ंक्शन केवल "डेटाबेस से उत्पाद प्राप्त करना" नहीं है। यह "उत्पाद प्राप्त करें, मैं इसे घंटों तक कैश कर सकता हूं, मैं इसे इस टैग के साथ अमान्य कर देता हूं"। एक घटक केवल "पेज प्रस्तुत करना" नहीं है। यह "यह तेज़ शेल है, यह टुकड़ा व्यक्तिगत है, यह स्ट्रीमिंग के लिए आता है।"
प्रथम दृष्टया यह अधिक काम जैसा लगता है। तब वह शांति का स्वरूप बन जाता है। प्रदर्शन निर्णय अब डिफ़ॉल्ट, अनुमान और जनजातीय स्मृति के संयोजन में छिपे नहीं हैं। वे कोड में हैं.