રિએક્ટ સસ્પેન્સ વોટરફોલને ઓળખતા અને દૂર કરતા શીખો. આ વ્યાપક માર્ગદર્શિકા પેરેલલ ફેચિંગ, Render-as-You-Fetch અને ઝડપી ગ્લોબલ એપ્લિકેશન્સ બનાવવા માટેની અન્ય અદ્યતન વ્યૂહરચનાઓને આવરી લે છે.
રિએક્ટ સસ્પેન્સ વોટરફોલ: સિક્વન્શિયલ ડેટા લોડિંગ ઓપ્ટિમાઇઝેશનમાં ઊંડાણપૂર્વકનો અભ્યાસ
એક સીમલેસ યુઝર અનુભવની સતત શોધમાં, ફ્રન્ટએન્ડ ડેવલપર્સ સતત એક ભયંકર દુશ્મન સામે લડી રહ્યા છે: લેટન્સી. વિશ્વભરના વપરાશકર્તાઓ માટે, દરેક મિલિસેકન્ડ મહત્વપૂર્ણ છે. ધીમી લોડ થતી એપ્લિકેશન ફક્ત વપરાશકર્તાઓને હતાશ જ નથી કરતી; તે સીધા જ એન્ગેજમેન્ટ, કન્વર્ઝન અને કંપનીના નફાને અસર કરી શકે છે. રિએક્ટે, તેના કમ્પોનન્ટ-આધારિત આર્કિટેક્ચર અને ઇકોસિસ્ટમ સાથે, જટિલ યુઝર ઇન્ટરફેસ બનાવવા માટે શક્તિશાળી સાધનો પૂરા પાડ્યા છે, અને તેની સૌથી પરિવર્તનશીલ સુવિધાઓમાંની એક રિએક્ટ સસ્પેન્સ છે.
સસ્પેન્સ અસિંક્રોનસ ઓપરેશન્સને હેન્ડલ કરવાની એક ડિક્લેરેટિવ રીત પ્રદાન કરે છે, જે આપણને આપણા કમ્પોનન્ટ ટ્રીમાં સીધા જ લોડિંગ સ્ટેટ્સ નિર્દિષ્ટ કરવાની મંજૂરી આપે છે. તે ડેટા ફેચિંગ, કોડ સ્પ્લિટિંગ અને અન્ય એસિંક કાર્યો માટે કોડને સરળ બનાવે છે. જો કે, આ શક્તિ સાથે પર્ફોર્મન્સ સંબંધિત નવી બાબતો પણ આવે છે. એક સામાન્ય અને ઘણીવાર સૂક્ષ્મ પર્ફોર્મન્સની ખામી જે ઊભી થઈ શકે છે તે છે "સસ્પેન્સ વોટરફોલ" — સિક્વન્શિયલ ડેટા-લોડિંગ ઓપરેશન્સની એક શૃંખલા જે તમારી એપ્લિકેશનના લોડ ટાઇમને નબળો પાડી શકે છે.
આ વ્યાપક માર્ગદર્શિકા રિએક્ટ ડેવલપર્સના વૈશ્વિક સમુદાય માટે બનાવવામાં આવી છે. આપણે સસ્પેન્સ વોટરફોલની ઘટનાનું વિચ્છેદન કરીશું, તેને કેવી રીતે ઓળખવું તે શોધીશું, અને તેને દૂર કરવા માટેની શક્તિશાળી વ્યૂહરચનાઓનું વિગતવાર વિશ્લેષણ પ્રદાન કરીશું. અંત સુધીમાં, તમે તમારી એપ્લિકેશનને ધીમી, આશ્રિત વિનંતીઓના ક્રમમાંથી અત્યંત ઓપ્ટિમાઇઝ્ડ, પેરેલલાઇઝ્ડ ડેટા-ફેચિંગ મશીનમાં રૂપાંતરિત કરવા માટે સજ્જ થશો, જે દરેક જગ્યાએ વપરાશકર્તાઓને શ્રેષ્ઠ અનુભવ પ્રદાન કરશે.
રિએક્ટ સસ્પેન્સને સમજવું: એક ઝડપી રિવિઝન
આપણે સમસ્યામાં ઊંડા ઉતરીએ તે પહેલાં, ચાલો સંક્ષિપ્તમાં રિએક્ટ સસ્પેન્સના મૂળભૂત ખ્યાલને ફરીથી જોઈએ. તેના હૃદયમાં, સસ્પેન્સ તમારા કમ્પોનન્ટ્સને રેન્ડર કરતા પહેલા કોઈ વસ્તુ માટે "રાહ" જોવાની મંજૂરી આપે છે, જેમાં તમારે જટિલ કન્ડિશનલ લોજિક (દા.ત., `if (isLoading) { ... }`) લખવાની જરૂર નથી.
જ્યારે સસ્પેન્સ બાઉન્ડ્રીમાં કોઈ કમ્પોનન્ટ સસ્પેન્ડ થાય છે (પ્રોમિસ થ્રો કરીને), ત્યારે રિએક્ટ તેને પકડી લે છે અને નિર્દિષ્ટ `fallback` UI દર્શાવે છે. એકવાર પ્રોમિસ રિઝોલ્વ થઈ જાય, પછી રિએક્ટ ડેટા સાથે કમ્પોનન્ટને ફરીથી રેન્ડર કરે છે.
ડેટા ફેચિંગ સાથેનું એક સરળ ઉદાહરણ આના જેવું દેખાઈ શકે છે:
- // api.js - અમારા ફેચ કોલને રેપ કરવા માટેની એક યુટિલિટી
- const cache = new Map();
- export function fetchData(url) {
- if (!cache.has(url)) {
- cache.set(url, getData(url));
- }
- return cache.get(url);
- }
- async function getData(url) {
- const res = await fetch(url);
- if (res.ok) {
- return res.json();
- } else {
- throw new Error('Failed to fetch');
- }
- }
અને અહીં એક કમ્પોનન્ટ છે જે સસ્પેન્સ-સુસંગત હૂકનો ઉપયોગ કરે છે:
- // useData.js - એક હૂક જે પ્રોમિસ થ્રો કરે છે
- import { fetchData } from './api';
- function useData(url) {
- const data = fetchData(url);
- if (data instanceof Promise) {
- throw data; // આ તે છે જે સસ્પેન્સને ટ્રિગર કરે છે
- }
- return data;
- }
અંતે, કમ્પોનન્ટ ટ્રી:
- // MyComponent.js
- import React, { Suspense } from 'react';
- import { useData } from './useData';
- function UserProfile() {
- const user = useData('/api/user/123');
- return <h1>Welcome, {user.name}</h1>;
- }
- function App() {
- return (
- <Suspense fallback={<h2>Loading user profile...</h2>}>
- <UserProfile />
- </Suspense>
- );
- }
આ એક ડેટા ડિપેન્ડન્સી માટે સુંદર રીતે કામ કરે છે. સમસ્યા ત્યારે ઊભી થાય છે જ્યારે આપણી પાસે બહુવિધ, નેસ્ટેડ ડેટા ડિપેન્ડન્સીઓ હોય છે.
"વોટરફોલ" શું છે? પર્ફોર્મન્સની અડચણને ઉઘાડી પાડવી
વેબ ડેવલપમેન્ટના સંદર્ભમાં, વોટરફોલ એ નેટવર્ક વિનંતીઓના ક્રમને સંદર્ભિત કરે છે જે એક પછી એક ક્રમમાં ચાલવી જોઈએ. શૃંખલામાં દરેક વિનંતી ત્યારે જ શરૂ થઈ શકે છે જ્યારે પાછલી વિનંતી સફળતાપૂર્વક પૂર્ણ થઈ હોય. આ એક ડિપેન્ડન્સી ચેઇન બનાવે છે જે તમારી એપ્લિકેશનના લોડિંગ સમયને નોંધપાત્ર રીતે ધીમો કરી શકે છે.
કલ્પના કરો કે તમે રેસ્ટોરન્ટમાં ત્રણ-કોર્સ ભોજનનો ઓર્ડર આપી રહ્યા છો. વોટરફોલ અભિગમ એ હશે કે તમે તમારા એપેટાઇઝરનો ઓર્ડર આપો, તેના આવવાની રાહ જુઓ અને તેને સમાપ્ત કરો, પછી તમારા મુખ્ય કોર્સનો ઓર્ડર આપો, તેની રાહ જુઓ અને તેને સમાપ્ત કરો, અને તે પછી જ ડેઝર્ટનો ઓર્ડર આપો. તમે રાહ જોવામાં જે કુલ સમય વિતાવો છો તે તમામ વ્યક્તિગત રાહ જોવાનો સમયનો સરવાળો છે. વધુ કાર્યક્ષમ અભિગમ એ હશે કે ત્રણેય કોર્સનો એક સાથે ઓર્ડર આપો. રસોડું પછી તેમને સમાંતર રીતે તૈયાર કરી શકે છે, જે તમારા કુલ રાહ જોવાનો સમયમાં ભારે ઘટાડો કરે છે.
રિએક્ટ સસ્પેન્સ વોટરફોલ એ રિએક્ટ કમ્પોનન્ટ ટ્રીમાં ડેટા ફેચિંગ માટે આ બિનકાર્યક્ષમ, સિક્વન્શિયલ પેટર્નનો ઉપયોગ છે. તે સામાન્ય રીતે ત્યારે થાય છે જ્યારે કોઈ પેરેન્ટ કમ્પોનન્ટ ડેટા ફેચ કરે છે અને પછી એક ચાઇલ્ડ કમ્પોનન્ટ રેન્ડર કરે છે જે, બદલામાં, પેરેન્ટ પાસેથી મળેલ મૂલ્યનો ઉપયોગ કરીને પોતાનો ડેટા ફેચ કરે છે.
એક ક્લાસિક વોટરફોલ ઉદાહરણ
ચાલો આપણા પાછલા ઉદાહરણને વિસ્તૃત કરીએ. આપણી પાસે એક `ProfilePage` છે જે યુઝર ડેટા ફેચ કરે છે. એકવાર તેની પાસે યુઝર ડેટા આવી જાય, તે એક `UserPosts` કમ્પોનન્ટ રેન્ડર કરે છે, જે પછી યુઝરની ID નો ઉપયોગ કરીને તેમની પોસ્ટ્સ ફેચ કરે છે.
- // પહેલાં: એક સ્પષ્ટ વોટરફોલ માળખું
- function ProfilePage({ userId }) {
- // ૧. પ્રથમ નેટવર્ક વિનંતી અહીંથી શરૂ થાય છે
- const user = useUserData(userId); // કમ્પોનન્ટ અહીં સસ્પેન્ડ થાય છે
- return (
- <div>
- <h1>{user.name}</h1>
- <p>{user.bio}</p>
- <Suspense fallback={<h3>Loading posts...</h3>}>
- // આ કમ્પોનન્ટ `user` ઉપલબ્ધ ન થાય ત્યાં સુધી માઉન્ટ પણ નથી થતો
- <UserPosts userId={user.id} />
- </Suspense>
- </div>
- );
- }
- function UserPosts({ userId }) {
- // ૨. બીજી નેટવર્ક વિનંતી અહીંથી શરૂ થાય છે, ફક્ત પહેલી પૂર્ણ થયા પછી
- const posts = useUserPosts(userId); // કમ્પોનન્ટ ફરીથી સસ્પેન્ડ થાય છે
- return (
- <ul>
- {posts.map(post => (<li key={post.id}>{post.title}</li>))}
- </ul>
- );
- }
ઘટનાઓનો ક્રમ આ મુજબ છે:
- `ProfilePage` રેન્ડર થાય છે અને `useUserData(userId)` ને કોલ કરે છે.
- એપ્લિકેશન સસ્પેન્ડ થાય છે, ફોલબેક UI બતાવે છે. યુઝર ડેટા માટેની નેટવર્ક વિનંતી ચાલુ છે.
- યુઝર ડેટા વિનંતી પૂર્ણ થાય છે. રિએક્ટ `ProfilePage` ને ફરીથી રેન્ડર કરે છે.
- હવે `user` ડેટા ઉપલબ્ધ છે, `UserPosts` પ્રથમ વખત રેન્ડર થાય છે.
- `UserPosts` `useUserPosts(userId)` ને કોલ કરે છે.
- એપ્લિકેશન ફરીથી સસ્પેન્ડ થાય છે, આંતરિક "Loading posts..." ફોલબેક બતાવે છે. પોસ્ટ્સ માટેની નેટવર્ક વિનંતી શરૂ થાય છે.
- પોસ્ટ્સ ડેટા વિનંતી પૂર્ણ થાય છે. રિએક્ટ ડેટા સાથે `UserPosts` ને ફરીથી રેન્ડર કરે છે.
કુલ લોડ સમય `સમય(યુઝર ફેચ) + સમય(પોસ્ટ્સ ફેચ)` છે. જો દરેક વિનંતી 500ms લે છે, તો વપરાશકર્તા પૂરી એક સેકન્ડ રાહ જુએ છે. આ એક ક્લાસિક વોટરફોલ છે, અને તે એક પર્ફોર્મન્સ સમસ્યા છે જેને આપણે હલ કરવી જ જોઈએ.
તમારી એપ્લિકેશનમાં સસ્પેન્સ વોટરફોલ્સને ઓળખવા
તમે કોઈ સમસ્યાને ઠીક કરો તે પહેલાં, તમારે તેને શોધવી પડશે. સદભાગ્યે, આધુનિક બ્રાઉઝર્સ અને ડેવલપમેન્ટ ટૂલ્સ વોટરફોલ્સને શોધવાનું પ્રમાણમાં સરળ બનાવે છે.
૧. બ્રાઉઝર ડેવલપર ટૂલ્સનો ઉપયોગ કરવો
તમારા બ્રાઉઝરના ડેવલપર ટૂલ્સમાં નેટવર્ક ટેબ તમારો શ્રેષ્ઠ મિત્ર છે. અહીં શું જોવાનું છે તે અહીં છે:
- સ્ટેર-સ્ટેપ પેટર્ન: જ્યારે તમે વોટરફોલ ધરાવતું પેજ લોડ કરો છો, ત્યારે તમે નેટવર્ક વિનંતીની ટાઇમલાઇનમાં એક વિશિષ્ટ સ્ટેર-સ્ટેપ અથવા કર્ણ પેટર્ન જોશો. એક વિનંતીનો પ્રારંભ સમય પાછલી વિનંતીના અંત સમય સાથે લગભગ સંપૂર્ણ રીતે સંરેખિત થશે.
- ટાઇમિંગ એનાલિસિસ: નેટવર્ક ટેબમાં "વોટરફોલ" કોલમનું પરીક્ષણ કરો. તમે દરેક વિનંતીના ટાઇમિંગનું વિભાજન જોઈ શકો છો (રાહ જોવી, કન્ટેન્ટ ડાઉનલોડ). એક સિક્વન્શિયલ ચેઇન દૃષ્ટિની રીતે સ્પષ્ટ હશે. જો વિનંતી B નો "પ્રારંભ સમય" વિનંતી A ના "અંત સમય" કરતાં વધુ હોય, તો સંભવતઃ તમારી પાસે વોટરફોલ છે.
૨. રિએક્ટ ડેવલપર ટૂલ્સનો ઉપયોગ કરવો
રિએક્ટ ડેવલપર ટૂલ્સ એક્સટેન્શન રિએક્ટ એપ્લિકેશન્સને ડિબગ કરવા માટે અનિવાર્ય છે.
- પ્રોફાઇલર: તમારા કમ્પોનન્ટના રેન્ડરિંગ લાઇફસાયકલનો પર્ફોર્મન્સ ટ્રેસ રેકોર્ડ કરવા માટે પ્રોફાઇલરનો ઉપયોગ કરો. વોટરફોલના કિસ્સામાં, તમે જોશો કે પેરેન્ટ કમ્પોનન્ટ રેન્ડર થાય છે, તેના ડેટાને રિઝોલ્વ કરે છે, અને પછી ફરીથી રેન્ડર ટ્રિગર કરે છે, જે પછી ચાઇલ્ડ કમ્પોનન્ટને માઉન્ટ અને સસ્પેન્ડ થવાનું કારણ બને છે. રેન્ડરિંગ અને સસ્પેન્ડિંગનો આ ક્રમ એક મજબૂત સૂચક છે.
- કમ્પોનન્ટ્સ ટેબ: રિએક્ટ ડેવટૂલ્સના નવા વર્ઝન બતાવે છે કે કયા કમ્પોનન્ટ્સ હાલમાં સસ્પેન્ડ થયેલા છે. પેરેન્ટ કમ્પોનન્ટને અનસસ્પેન્ડ થતો જોવો, અને તરત જ ચાઇલ્ડ કમ્પોનન્ટ સસ્પેન્ડ થતો જોવો, તમને વોટરફોલના સ્ત્રોતને ઓળખવામાં મદદ કરી શકે છે.
૩. સ્ટેટિક કોડ એનાલિસિસ
ક્યારેક, તમે ફક્ત કોડ વાંચીને જ સંભવિત વોટરફોલ્સને ઓળખી શકો છો. આ પેટર્ન માટે જુઓ:
- નેસ્ટેડ ડેટા ડિપેન્ડન્સીઝ: એક કમ્પોનન્ટ જે ડેટા ફેચ કરે છે અને તે ફેચના પરિણામને ચાઇલ્ડ કમ્પોનન્ટને પ્રોપ તરીકે પાસ કરે છે, જે પછી તે પ્રોપનો ઉપયોગ વધુ ડેટા ફેચ કરવા માટે કરે છે. આ સૌથી સામાન્ય પેટર્ન છે.
- સિક્વન્શિયલ હુક્સ: એક કમ્પોનન્ટ જે એક કસ્ટમ ડેટા-ફેચિંગ હૂકના ડેટાનો ઉપયોગ બીજા હૂકમાં કોલ કરવા માટે કરે છે. જોકે આ સખત રીતે પેરેન્ટ-ચાઇલ્ડ વોટરફોલ નથી, તે એક કમ્પોનન્ટની અંદર સમાન સિક્વન્શિયલ અવરોધ બનાવે છે.
વોટરફોલ્સને ઓપ્ટિમાઇઝ અને દૂર કરવાની વ્યૂહરચનાઓ
એકવાર તમે વોટરફોલને ઓળખી લો, પછી તેને ઠીક કરવાનો સમય છે. તમામ ઓપ્ટિમાઇઝેશન વ્યૂહરચનાઓનો મૂળભૂત સિદ્ધાંત સિક્વન્શિયલ ફેચિંગથી પેરેલલ ફેચિંગમાં સ્વિચ કરવાનો છે. અમે બધી જરૂરી નેટવર્ક વિનંતીઓને શક્ય તેટલી વહેલી અને એક સાથે શરૂ કરવા માંગીએ છીએ.
વ્યૂહરચના ૧: `Promise.all` સાથે પેરેલલ ડેટા ફેચિંગ
આ સૌથી સીધો અભિગમ છે. જો તમને અગાઉથી જરૂરી તમામ ડેટા ખબર હોય, તો તમે બધી વિનંતીઓને એક સાથે શરૂ કરી શકો છો અને તે બધાના પૂર્ણ થવાની રાહ જોઈ શકો છો.
ખ્યાલ: ફેચને નેસ્ટ કરવાને બદલે, તેમને સામાન્ય પેરેન્ટમાં અથવા તમારી એપ્લિકેશન લોજિકમાં ઉચ્ચ સ્તરે ટ્રિગર કરો, તેમને `Promise.all` માં રેપ કરો, અને પછી ડેટાને તે કમ્પોનન્ટ્સને પાસ કરો જેમને તેની જરૂર છે.
ચાલો આપણા `ProfilePage` ઉદાહરણને રિફેક્ટર કરીએ. આપણે એક નવો કમ્પોનન્ટ, `ProfilePageData` બનાવી શકીએ છીએ, જે બધું સમાંતર રીતે ફેચ કરે છે.
- // api.js (ફેચ ફંક્શન્સને એક્સપોઝ કરવા માટે સંશોધિત)
- export async function fetchUser(userId) { ... }
- export async function fetchPostsForUser(userId) { ... }
- // પહેલાં: વોટરફોલ
- function ProfilePage({ userId }) {
- const user = useUserData(userId); // વિનંતી ૧
- return <UserPosts userId={user.id} />; // વિનંતી ૨ વિનંતી ૧ પૂર્ણ થયા પછી શરૂ થાય છે
- }
- // પછી: પેરેલલ ફેચિંગ
- // રિસોર્સ બનાવતી યુટિલિટી
- function createProfileData(userId) {
- const userPromise = fetchUser(userId);
- const postsPromise = fetchPostsForUser(userId);
- return {
- user: wrapPromise(userPromise),
- posts: wrapPromise(postsPromise),
- };
- }
- // `wrapPromise` એક હેલ્પર છે જે કમ્પોનન્ટને પ્રોમિસનું પરિણામ વાંચવા દે છે.
- // જો પ્રોમિસ પેન્ડિંગ હોય, તો તે પ્રોમિસને થ્રો કરે છે.
- // જો પ્રોમિસ રિઝોલ્વ્ડ હોય, તો તે મૂલ્ય પરત કરે છે.
- // જો પ્રોમિસ રિજેક્ટેડ હોય, તો તે એરર થ્રો કરે છે.
- const resource = createProfileData('123');
- function ProfilePage() {
- const user = resource.user.read(); // વાંચે છે અથવા સસ્પેન્ડ કરે છે
- return (
- <div>
- <h1>{user.name}</h1>
- <Suspense fallback={<h3>Loading posts...</h3>}>
- <UserPosts />
- </Suspense>
- </div>
- );
- }
- function UserPosts() {
- const posts = resource.posts.read(); // વાંચે છે અથવા સસ્પેન્ડ કરે છે
- return <ul>...</ul>;
- }
આ સુધારેલી પેટર્નમાં, `createProfileData` એકવાર કોલ થાય છે. તે તરત જ યુઝર અને પોસ્ટ્સ બંનેની ફેચ વિનંતીઓ શરૂ કરે છે. કુલ લોડિંગ સમય હવે બે વિનંતીઓમાંથી સૌથી ધીમી વિનંતી દ્વારા નક્કી થાય છે, તેમના સરવાળા દ્વારા નહીં. જો બંને 500ms લે છે, તો કુલ રાહ હવે 1000ms ને બદલે ~500ms છે. આ એક મોટો સુધારો છે.
વ્યૂહરચના ૨: ડેટા ફેચિંગને સામાન્ય પૂર્વજ (Common Ancestor) પર લઈ જવું
આ વ્યૂહરચના પ્રથમ વ્યૂહરચનાનો જ એક પ્રકાર છે. તે ખાસ કરીને ત્યારે ઉપયોગી છે જ્યારે તમારી પાસે સિબ્લિંગ કમ્પોનન્ટ્સ હોય જે સ્વતંત્ર રીતે ડેટા ફેચ કરે છે, જે સંભવિતપણે તેમની વચ્ચે વોટરફોલનું કારણ બની શકે છે જો તે સિક્વન્શિયલી રેન્ડર થાય.
ખ્યાલ: જે કમ્પોનન્ટ્સને ડેટાની જરૂર હોય તે બધા માટે એક સામાન્ય પેરેન્ટ કમ્પોનન્ટ ઓળખો. ડેટા-ફેચિંગ લોજિકને તે પેરેન્ટમાં ખસેડો. પેરેન્ટ પછી ફેચને સમાંતર રીતે એક્ઝિક્યુટ કરી શકે છે અને ડેટાને પ્રોપ્સ તરીકે નીચે પાસ કરી શકે છે. આ ડેટા ફેચિંગ લોજિકને કેન્દ્રિત કરે છે અને ખાતરી કરે છે કે તે શક્ય તેટલું વહેલું ચાલે છે.
- // પહેલાં: સિબ્લિંગ્સ સ્વતંત્ર રીતે ફેચ કરે છે
- function Dashboard() {
- return (
- <div>
- <Suspense fallback={...}><UserInfo /></Suspense>
- <Suspense fallback={...}><Notifications /></Suspense>
- </div>
- );
- }
- // UserInfo યુઝર ડેટા ફેચ કરે છે, Notifications નોટિફિકેશન ડેટા ફેચ કરે છે.
- // રિએક્ટ *શક્ય છે કે* તેમને સિક્વન્શિયલી રેન્ડર કરે, જે એક નાનો વોટરફોલ બનાવે છે.
- // પછી: પેરેન્ટ બધા ડેટાને સમાંતર રીતે ફેચ કરે છે
- const dashboardResource = createDashboardResource();
- function Dashboard() {
- // આ કમ્પોનન્ટ ફેચ કરતું નથી, તે ફક્ત રેન્ડરિંગનું સંકલન કરે છે.
- return (
- <div>
- <Suspense fallback={...}>
- <UserInfo resource={dashboardResource} />
- <Notifications resource={dashboardResource} />
- </Suspense>
- </div>
- );
- }
- function UserInfo({ resource }) {
- const user = resource.user.read();
- return <div>Welcome, {user.name}</div>;
- }
- function Notifications({ resource }) {
- const notifications = resource.notifications.read();
- return <div>You have {notifications.length} new notifications.</div>;
- }
ફેચિંગ લોજિકને ઉપર લઈ જઈને, અમે સમાંતર એક્ઝિક્યુશનની ખાતરી આપીએ છીએ અને સમગ્ર ડેશબોર્ડ માટે એક સુસંગત લોડિંગ અનુભવ પ્રદાન કરીએ છીએ.
વ્યૂહરચના ૩: કેશ સાથે ડેટા-ફેચિંગ લાઇબ્રેરીનો ઉપયોગ કરવો
મેન્યુઅલી પ્રોમિસનું સંચાલન કરવું કામ કરે છે, પરંતુ મોટી એપ્લિકેશન્સમાં તે બોજારૂપ બની શકે છે. અહીં જ રિએક્ટ ક્વેરી (હવે ટેનસ્ટેક ક્વેરી), SWR, અથવા રીલે જેવી સમર્પિત ડેટા-ફેચિંગ લાઇબ્રેરીઓ ચમકે છે. આ લાઇબ્રેરીઓ ખાસ કરીને વોટરફોલ જેવી સમસ્યાઓ હલ કરવા માટે બનાવવામાં આવી છે.
ખ્યાલ: આ લાઇબ્રેરીઓ ગ્લોબલ અથવા પ્રોવાઇડર-લેવલ કેશ જાળવે છે. જ્યારે કોઈ કમ્પોનન્ટ ડેટાની વિનંતી કરે છે, ત્યારે લાઇબ્રેરી પહેલા કેશ તપાસે છે. જો બહુવિધ કમ્પોનન્ટ્સ એક સાથે સમાન ડેટાની વિનંતી કરે છે, તો લાઇબ્રેરી વિનંતીને ડી-ડુપ્લિકેટ કરવા માટે પૂરતી સ્માર્ટ છે, ફક્ત એક જ વાસ્તવિક નેટવર્ક વિનંતી મોકલે છે.
તે કેવી રીતે મદદ કરે છે:
- વિનંતી ડીડુપ્લિકેશન: જો `ProfilePage` અને `UserPosts` બંને એક જ યુઝર ડેટાની વિનંતી કરે (દા.ત., `useQuery(['user', userId])`), તો લાઇબ્રેરી ફક્ત એક જ વાર નેટવર્ક વિનંતી કરશે.
- કેશિંગ: જો ડેટા પાછલી વિનંતીથી કેશમાં પહેલેથી જ હોય, તો પછીની વિનંતીઓ તરત જ રિઝોલ્વ થઈ શકે છે, જે કોઈપણ સંભવિત વોટરફોલને તોડે છે.
- ડિફૉલ્ટ રૂપે પેરેલલ: હૂક-આધારિત પ્રકૃતિ તમને તમારા કમ્પોનન્ટ્સના ટોચના સ્તરે `useQuery` કોલ કરવા માટે પ્રોત્સાહિત કરે છે. જ્યારે રિએક્ટ રેન્ડર કરે છે, ત્યારે તે આ બધા હૂક્સને લગભગ એક સાથે ટ્રિગર કરશે, જે ડિફૉલ્ટ રૂપે પેરેલલ ફેચ તરફ દોરી જશે.
- // રિએક્ટ ક્વેરી સાથેનું ઉદાહરણ
- function ProfilePage({ userId }) {
- // આ હૂક રેન્ડર પર તરત જ તેની વિનંતી શરૂ કરે છે
- const { data: user } = useQuery(['user', userId], () => fetchUser(userId), { suspense: true });
- return (
- <div>
- <h1>{user.name}</h1>
- <Suspense fallback={<h3>Loading posts...</h3>}>
- // જોકે આ નેસ્ટેડ છે, રિએક્ટ ક્વેરી ઘણીવાર પ્રી-ફેચ અથવા પેરેલલ ફેચને અસરકારક રીતે કરે છે
- <UserPosts userId={user.id} />
- </Suspense>
- </div>
- );
- }
- function UserPosts({ userId }) {
- const { data: posts } = useQuery(['posts', userId], () => fetchPostsForUser(userId), { suspense: true });
- return <ul>...</ul>;
- }
જ્યારે કોડ માળખું હજી પણ વોટરફોલ જેવું દેખાઈ શકે છે, રિએક્ટ ક્વેરી જેવી લાઇબ્રેરીઓ ઘણીવાર તેને ઘટાડવા માટે પૂરતી સ્માર્ટ હોય છે. વધુ સારા પર્ફોર્મન્સ માટે, તમે તેમના પ્રી-ફેચિંગ APIs નો ઉપયોગ કરીને સ્પષ્ટપણે ડેટા લોડ કરવાનું શરૂ કરી શકો છો તે પહેલાં કે કોઈ કમ્પોનન્ટ રેન્ડર પણ થાય.
વ્યૂહરચના ૪: રેન્ડર-એઝ-યુ-ફેચ પેટર્ન
આ સૌથી અદ્યતન અને કાર્યક્ષમ પેટર્ન છે, જેની રિએક્ટ ટીમ દ્વારા ભારે હિમાયત કરવામાં આવી છે. તે સામાન્ય ડેટા-ફેચિંગ મોડલ્સને તેમના માથા પર ફેરવી દે છે.
- ફેચ-ઓન-રેન્ડર (સમસ્યા): કમ્પોનન્ટ રેન્ડર કરો -> useEffect/hook ફેચ ટ્રિગર કરે છે. (વોટરફોલ્સ તરફ દોરી જાય છે).
- ફેચ-ધેન-રેન્ડર: ફેચ ટ્રિગર કરો -> રાહ જુઓ -> ડેટા સાથે કમ્પોનન્ટ રેન્ડર કરો. (વધુ સારું, પરંતુ હજી પણ રેન્ડરિંગને બ્લોક કરી શકે છે).
- રેન્ડર-એઝ-યુ-ફેચ (ઉકેલ): ફેચ ટ્રિગર કરો -> તરત જ કમ્પોનન્ટ રેન્ડર કરવાનું શરૂ કરો. જો ડેટા હજી તૈયાર ન હોય તો કમ્પોનન્ટ સસ્પેન્ડ થાય છે.
ખ્યાલ: ડેટા ફેચિંગને કમ્પોનન્ટ લાઇફસાયકલથી સંપૂર્ણપણે અલગ કરો. તમે નેટવર્ક વિનંતીને શક્ય તેટલી વહેલી ક્ષણે શરૂ કરો છો—ઉદાહરણ તરીકે, રાઉટિંગ લેયરમાં અથવા ઇવેન્ટ હેન્ડલરમાં (જેમ કે લિંક પર ક્લિક કરવું)—તે પહેલાં કે જે કમ્પોનન્ટને ડેટાની જરૂર છે તે રેન્ડર કરવાનું શરૂ પણ કરે.
- // ૧. રાઉટર અથવા ઇવેન્ટ હેન્ડલરમાં ફેચિંગ શરૂ કરો
- import { createProfileData } from './api';
- // જ્યારે વપરાશકર્તા પ્રોફાઇલ પેજની લિંક પર ક્લિક કરે છે:
- function onProfileLinkClick(userId) {
- const resource = createProfileData(userId);
- navigateTo(`/profile/${userId}`, { state: { resource } });
- }
- // ૨. પેજ કમ્પોનન્ટ રિસોર્સ મેળવે છે
- function ProfilePage() {
- // તે રિસોર્સ મેળવો જે પહેલેથી જ શરૂ થઈ ચૂક્યો છે
- const resource = useLocation().state.resource;
- return (
- <Suspense fallback={<h1>Loading profile...</h1>}>
- <ProfileDetails resource={resource} />
- <ProfilePosts resource={resource} />
- </Suspense>
- );
- }
- // ૩. ચાઇલ્ડ કમ્પોનન્ટ્સ રિસોર્સમાંથી વાંચે છે
- function ProfileDetails({ resource }) {
- const user = resource.user.read(); // વાંચે છે અથવા સસ્પેન્ડ કરે છે
- return <h1>{user.name}</h1>;
- }
- function ProfilePosts({ resource }) {
- const posts = resource.posts.read(); // વાંચે છે અથવા સસ્પેન્ડ કરે છે
- return <ul>...</ul>;
- }
આ પેટર્નની સુંદરતા તેની કાર્યક્ષમતામાં છે. યુઝર અને પોસ્ટ્સ ડેટા માટેની નેટવર્ક વિનંતીઓ તે જ ક્ષણે શરૂ થાય છે જ્યારે વપરાશકર્તા નેવિગેટ કરવાનો તેમનો ઇરાદો દર્શાવે છે. `ProfilePage` માટે જાવાસ્ક્રિપ્ટ બંડલ લોડ કરવામાં અને રિએક્ટને રેન્ડરિંગ શરૂ કરવામાં જે સમય લાગે છે તે ડેટા ફેચિંગ સાથે સમાંતર થાય છે. આ લગભગ તમામ રોકી શકાય તેવા રાહ જોવાનો સમય દૂર કરે છે.
ઓપ્ટિમાઇઝેશન વ્યૂહરચનાઓની તુલના: કઈ પસંદ કરવી?
યોગ્ય વ્યૂહરચના પસંદ કરવી તે તમારી એપ્લિકેશનની જટિલતા અને પર્ફોર્મન્સના લક્ષ્યો પર આધાર રાખે છે.
- પેરેલલ ફેચિંગ (`Promise.all` / મેન્યુઅલ ઓર્કેસ્ટ્રેશન):
- ફાયદા: કોઈ બાહ્ય લાઇબ્રેરીઓની જરૂર નથી. એક જ જગ્યાએ ડેટાની જરૂરિયાતો માટે વૈચારિક રીતે સરળ. પ્રક્રિયા પર સંપૂર્ણ નિયંત્રણ.
- ગેરફાયદા: સ્ટેટ, એરર્સ અને કેશિંગને મેન્યુઅલી મેનેજ કરવું જટિલ બની શકે છે. મજબૂત માળખા વિના સારી રીતે સ્કેલ થતું નથી.
- આ માટે શ્રેષ્ઠ: સરળ ઉપયોગના કિસ્સાઓ, નાની એપ્લિકેશન્સ, અથવા પર્ફોર્મન્સ-ક્રિટિકલ વિભાગો જ્યાં તમે લાઇબ્રેરી ઓવરહેડ ટાળવા માંગો છો.
- ડેટા ફેચિંગને ઉપર લઈ જવું:
- ફાયદા: કમ્પોનન્ટ ટ્રીમાં ડેટા ફ્લો ગોઠવવા માટે સારું. ચોક્કસ વ્યુ માટે ફેચિંગ લોજિકને કેન્દ્રિત કરે છે.
- ગેરફાયદા: પ્રોપ ડ્રિલિંગ તરફ દોરી શકે છે અથવા ડેટા નીચે પાસ કરવા માટે સ્ટેટ મેનેજમેન્ટ સોલ્યુશનની જરૂર પડી શકે છે. પેરેન્ટ કમ્પોનન્ટ મોટો થઈ શકે છે.
- આ માટે શ્રેષ્ઠ: જ્યારે બહુવિધ સિબ્લિંગ કમ્પોનન્ટ્સ ડેટા પરની નિર્ભરતા શેર કરે છે જે તેમના સામાન્ય પેરેન્ટથી ફેચ કરી શકાય છે.
- ડેટા-ફેચિંગ લાઇબ્રેરીઓ (રિએક્ટ ક્વેરી, SWR):
- ફાયદા: સૌથી મજબૂત અને ડેવલપર-ફ્રેન્ડલી સોલ્યુશન. કેશિંગ, ડીડુપ્લિકેશન, બેકગ્રાઉન્ડ રિફેચિંગ અને એરર સ્ટેટ્સને આઉટ-ઓફ-ધ-બોક્સ હેન્ડલ કરે છે. બોઇલરપ્લેટમાં ભારે ઘટાડો કરે છે.
- ગેરફાયદા: તમારા પ્રોજેક્ટમાં લાઇબ્રેરી ડિપેન્ડન્સી ઉમેરે છે. લાઇબ્રેરીના ચોક્કસ API શીખવાની જરૂર પડે છે.
- આ માટે શ્રેષ્ઠ: મોટાભાગની આધુનિક રિએક્ટ એપ્લિકેશન્સ. આ કોઈપણ પ્રોજેક્ટ માટે ડિફૉલ્ટ પસંદગી હોવી જોઈએ જેમાં નોંધપાત્ર ડેટા આવશ્યકતાઓ હોય.
- રેન્ડર-એઝ-યુ-ફેચ:
- ફાયદા: ઉચ્ચતમ-પર્ફોર્મન્સ પેટર્ન. કમ્પોનન્ટ કોડ લોડિંગ અને ડેટા ફેચિંગને ઓવરલેપ કરીને પેરેલલિઝમને મહત્તમ કરે છે.
- ગેરફાયદા: વિચારસરણીમાં નોંધપાત્ર ફેરફારની જરૂર પડે છે. જો રીલે અથવા Next.js જેવા ફ્રેમવર્કનો ઉપયોગ ન કરતા હોય કે જેમાં આ પેટર્ન બિલ્ટ-ઇન હોય તો સેટઅપ કરવા માટે વધુ બોઇલરપ્લેટ સામેલ થઈ શકે છે.
- આ માટે શ્રેષ્ઠ: લેટન્સી-ક્રિટિકલ એપ્લિકેશન્સ જ્યાં દરેક મિલિસેકન્ડ મહત્વપૂર્ણ હોય. રાઉટિંગને ડેટા ફેચિંગ સાથે એકીકૃત કરતા ફ્રેમવર્ક આ પેટર્ન માટે આદર્શ વાતાવરણ છે.
વૈશ્વિક વિચારણાઓ અને શ્રેષ્ઠ પદ્ધતિઓ
વૈશ્વિક સમુદાય માટે નિર્માણ કરતી વખતે, વોટરફોલ્સને દૂર કરવું માત્ર એક સારી બાબત નથી—તે આવશ્યક છે.
- લેટન્સી એકસમાન નથી: તમારા સર્વરની નજીકના વપરાશકર્તા માટે 200ms નો વોટરફોલ ભાગ્યે જ ધ્યાનપાત્ર હોઈ શકે છે, પરંતુ ઉચ્ચ-લેટન્સી મોબાઇલ ઇન્ટરનેટ ધરાવતા બીજા ખંડના વપરાશકર્તા માટે, તે જ વોટરફોલ તેમના લોડ ટાઇમમાં સેકન્ડો ઉમેરી શકે છે. વિનંતીઓને સમાંતર કરવી એ ઉચ્ચ લેટન્સીની અસરને ઘટાડવાનો સૌથી અસરકારક માર્ગ છે.
- કોડ સ્પ્લિટિંગ વોટરફોલ્સ: વોટરફોલ્સ ફક્ત ડેટા સુધી મર્યાદિત નથી. એક સામાન્ય પેટર્ન છે `React.lazy()` દ્વારા કમ્પોનન્ટ બંડલ લોડ કરવું, જે પછી પોતાનો ડેટા ફેચ કરે છે. આ એક કોડ -> ડેટા વોટરફોલ છે. રેન્ડર-એઝ-યુ-ફેચ પેટર્ન કમ્પોનન્ટ અને તેના ડેટા બંનેને પ્રીલોડ કરીને આને હલ કરવામાં મદદ કરે છે જ્યારે વપરાશકર્તા નેવિગેટ કરે છે.
- ગ્રેસફુલ એરર હેન્ડલિંગ: જ્યારે તમે ડેટા સમાંતર રીતે ફેચ કરો છો, ત્યારે તમારે આંશિક નિષ્ફળતાઓને ધ્યાનમાં લેવી આવશ્યક છે. જો યુઝર ડેટા લોડ થાય પરંતુ પોસ્ટ્સ નિષ્ફળ જાય તો શું થાય? તમારું UI આને ગ્રેસફુલી હેન્ડલ કરવા સક્ષમ હોવું જોઈએ, કદાચ યુઝર પ્રોફાઇલને પોસ્ટ્સ વિભાગમાં એરર મેસેજ સાથે બતાવીને. રિએક્ટ ક્વેરી જેવી લાઇબ્રેરીઓ પ્રતિ-ક્વેરી એરર સ્ટેટ્સને હેન્ડલ કરવા માટે સ્પષ્ટ પેટર્ન પ્રદાન કરે છે.
- અર્થપૂર્ણ ફોલબેક્સ: ડેટા લોડ થતો હોય ત્યારે સારો વપરાશકર્તા અનુભવ પ્રદાન કરવા માટે `
` ના `fallback` પ્રોપનો ઉપયોગ કરો. એક સામાન્ય સ્પિનરને બદલે, સ્કેલેટન લોડર્સનો ઉપયોગ કરો જે અંતિમ UI ના આકારનું અનુકરણ કરે છે. આ જોવામાં આવતી કામગીરીમાં સુધારો કરે છે અને નેટવર્ક ધીમું હોય ત્યારે પણ એપ્લિકેશનને ઝડપી અનુભવ કરાવે છે.
નિષ્કર્ષ
રિએક્ટ સસ્પેન્સ વોટરફોલ એક સૂક્ષ્મ પરંતુ નોંધપાત્ર પર્ફોર્મન્સની અડચણ છે જે વપરાશકર્તાના અનુભવને બગાડી શકે છે, ખાસ કરીને વૈશ્વિક વપરાશકર્તા આધાર માટે. તે સિક્વન્શિયલ, નેસ્ટેડ ડેટા ફેચિંગની કુદરતી પરંતુ બિનકાર્યક્ષમ પેટર્નથી ઉદ્ભવે છે. આ સમસ્યાને હલ કરવાની ચાવી એક માનસિક પરિવર્તન છે: રેન્ડર પર ફેચ કરવાનું બંધ કરો, અને શક્ય તેટલું વહેલું, સમાંતર રીતે ફેચ કરવાનું શરૂ કરો.
અમે મેન્યુઅલ પ્રોમિસ ઓર્કેસ્ટ્રેશનથી લઈને અત્યંત કાર્યક્ષમ રેન્ડર-એઝ-યુ-ફેચ પેટર્ન સુધીની શક્તિશાળી વ્યૂહરચનાઓની શ્રેણીની શોધ કરી છે. મોટાભાગની આધુનિક એપ્લિકેશન્સ માટે, ટેનસ્ટેક ક્વેરી અથવા SWR જેવી સમર્પિત ડેટા-ફેચિંગ લાઇબ્રેરી અપનાવવી એ પર્ફોર્મન્સ, ડેવલપર અનુભવ અને કેશિંગ અને ડીડુપ્લિકેશન જેવી શક્તિશાળી સુવિધાઓનું શ્રેષ્ઠ સંતુલન પૂરું પાડે છે.
આજથી જ તમારી એપ્લિકેશનના નેટવર્ક ટેબનું ઓડિટ કરવાનું શરૂ કરો. તે સ્પષ્ટ સ્ટેર-સ્ટેપ પેટર્ન શોધો. ડેટા-ફેચિંગ વોટરફોલ્સને ઓળખીને અને દૂર કરીને, તમે તમારા વપરાશકર્તાઓને નોંધપાત્ર રીતે ઝડપી, વધુ પ્રવાહી અને વધુ સ્થિતિસ્થાપક એપ્લિકેશન પહોંચાડી શકો છો—ભલે તેઓ વિશ્વમાં ગમે ત્યાં હોય.