Skip to content

રેન્ડરિંગ મિકેનિઝમ (Rendering Mechanism)

Vue કેવી રીતે ટેમ્પલેટ લે છે અને તેને વાસ્તવિક DOM નોડ્સમાં ફેરવે છે? Vue તે DOM નોડ્સને કાર્યક્ષમ રીતે કેવી રીતે અપડેટ કરે છે? અમે અહીં Vue ના આંતરિક રેન્ડરિંગ મિકેનિઝમ (rendering mechanism) માં ઊંડા ઉતરીને આ પ્રશ્નો પર થોડો પ્રકાશ પાડવાનો પ્રયાસ કરીશું.

વર્ચ્યુઅલ DOM (Virtual DOM)

તમે કદાચ "વર્ચ્યુઅલ DOM" શબ્દ વિશે સાંભળ્યું જ હશે, જેના પર Vue ની રેન્ડરિંગ સિસ્ટમ આધારિત છે.

વર્ચ્યુઅલ DOM (Virtual DOM - VDOM) એ એક પ્રોગ્રામિંગ કન્સેપ્ટ છે જ્યાં UI ની એક આદર્શ, અથવા "વર્ચ્યુઅલ", રિપ્રેઝન્ટેશન મેમરીમાં રાખવામાં આવે છે અને "રિયલ (real)" DOM સાથે સિંક કરવામાં આવે છે. આ કન્સેપ્ટ સૌપ્રથમ React દ્વારા રજૂ કરવામાં આવ્યો હતો, અને Vue સહિત વિવિધ અમલીકરણો સાથે અન્ય ઘણા ફ્રેમવર્ક્સમાં અપનાવવામાં આવ્યો છે.

વર્ચ્યુઅલ DOM એ વિશિષ્ટ ટેક્નોલોજી કરતાં વધુ એક પેટર્ન છે, તેથી તેનું કોઈ એક નિશ્ચિત અમલીકરણ નથી. આપણે એક સરળ ઉદાહરણનો ઉપયોગ કરીને આ વિચારને સમજાવી શકીએ છીએ:

js
const vnode = {
  type: 'div',
  props: {
    id: 'hello'
  },
  children: [
    /* વધુ vnodes */
  ]
}

અહીં, vnode એ એક સાદો JavaScript ઓબ્જેક્ટ ("virtual node") છે જે <div> એલિમેન્ટનું પ્રતિનિધિત્વ કરે છે. તેમાં વાસ્તવિક એલિમેન્ટ બનાવવા માટે જરૂરી બધી માહિતી શામેલ છે. તેમાં વધુ ચાઈલ્ડ vnodes પણ છે, જે તેને વર્ચ્યુઅલ DOM ટ્રીના રૂટ (root) બનાવે છે.

રનટાઇમ રેન્ડરર વર્ચ્યુઅલ DOM ટ્રી દ્વારા નેવિગેટ કરી શકે છે અને તેમાંથી વાસ્તવિક DOM ટ્રી બનાવી શકે છે. આ પ્રક્રિયાને માઉન્ટ (mount) કહેવામાં આવે છે.

જો આપણી પાસે વર્ચ્યુઅલ DOM ટ્રીની બે નકલો હોય, તો રેન્ડરર બંને ટ્રીની તુલના કરી શકે છે, તફાવતો શોધી શકે છે અને તે ફેરફારોને વાસ્તવિક DOM પર લાગુ કરી શકે છે. આ પ્રક્રિયાને પેચ (patch) કહેવામાં આવે છે, જે "ડિફિંગ (diffing)" તરીકે પણ ઓળખાય છે.

વર્ચ્યુઅલ DOM નો મુખ્ય ફાયદો એ છે કે તે ડેવલપરને પ્રોગ્રામેટિક રીતે ઇચ્છિત UI સ્ટ્રક્ચર્સને ડિક્લેરેટિવ રીતે બનાવવાની, નિરીક્ષણ કરવાની અને કમ્પોઝ કરવાની ક્ષમતા આપે છે, જ્યારે સીધા DOM મેનીપ્યુલેશનને રેન્ડરર પર છોડી દે છે.

રેન્ડર પાઇપલાઇન (Render Pipeline)

જ્યારે Vue ઘટક માઉન્ટ થાય છે ત્યારે ઉચ્ચ સ્તરે આ જ થાય છે:

૧. કમ્પાઇલ (Compile): Vue ટેમ્પલેટ્સ રેન્ડર ફંક્શન્સ (render functions) માં કમ્પાઇલ કરવામાં આવે છે: એવા ફંક્શન્સ જે વર્ચ્યુઅલ DOM ટ્રી પરત કરે છે. આ સ્ટેપ કાં તો બિલ્ડ સ્ટેપ દ્વારા સમય પહેલા કરી શકાય છે, અથવા રનટાઇમ કમ્પાઇલરનો ઉપયોગ કરીને રન-ટાઇમમાં કરી શકાય છે.

૨. માઉન્ટ (Mount): રનટાઇમ રેન્ડરર રેન્ડર ફંક્શન્સને બોલાવે છે, પરત કરેલા વર્ચ્યુઅલ DOM ટ્રી દ્વારા ચાલે છે અને તેના આધારે વાસ્તવિક DOM નોડ્સ બનાવે છે. આ સ્ટેપ રિએક્ટિવ ઇફેક્ટ (reactive effect) તરીકે કરવામાં આવે છે, તેથી તે ઉપયોગમાં લેવાયેલ તમામ રિએક્ટિવ ડિપેન્ડન્સીસને ટ્રેક કરે છે.

૩. પેચ (Patch): જ્યારે માઉન્ટ દરમિયાન ઉપયોગમાં લેવાતી ડિપેન્ડન્સી બદલાય છે, ત્યારે ઇફેક્ટ ફરીથી ચાલે છે. આ વખતે, નવું, અપડેટેડ વર્ચ્યુઅલ DOM ટ્રી બનાવવામાં આવે છે. રનટાઇમ રેન્ડરર નવા ટ્રી દ્વારા ચાલે છે, જૂના સાથે તેની તુલના કરે છે અને વાસ્તવિક DOM પર જરૂરી અપડેટ્સ લાગુ કરે છે.

રેન્ડર પાઇપલાઇન (render pipeline)

ટેમ્પલેટ્સ વિરુદ્ધ રેન્ડર ફંક્શન્સ (Templates vs. Render Functions)

Vue ટેમ્પલેટ્સ વર્ચ્યુઅલ DOM રેન્ડર ફંક્શન્સમાં કમ્પાઇલ કરવામાં આવે છે. Vue એવા APIs પણ પ્રદાન કરે છે જે આપણને ટેમ્પલેટ કમ્પાલેશન સ્ટેપને છોડી દેવાની અને સીધા રેન્ડર ફંક્શન્સ લખવાની મંજૂરી આપે છે. અત્યંત ડાયનેમિક લોજિક સાથે કામ કરતી વખતે રેન્ડર ફંક્શન્સ ટેમ્પલેટ્સ કરતા વધુ લવચીક હોય છે, કારણ કે તમે JavaScript ની સંપૂર્ણ શક્તિનો ઉપયોગ કરીને vnodes સાથે કામ કરી શકો છો.

તો પછી Vue શા માટે ડિફોલ્ટ રૂપે ટેમ્પલેટ્સની ભલામણ કરે છે? તેના ઘણા કારણો છે:

૧. ટેમ્પલેટ્સ વાસ્તવિક HTML ની નજીક છે. આ હયાત HTML સ્નિપેટ્સનો ફરીથી ઉપયોગ કરવાનું, એક્સેસિબિલિટીની શ્રેષ્ઠ પ્રેક્ટિસ લાગુ કરવાનું, CSS સાથે સ્ટાઇલ કરવાનું અને ડિઝાઇનર્સ માટે સમજવામાં અને ફેરફાર કરવાનું સરળ બનાવે છે.

૨. ટેમ્પલેટ્સ તેમના વધુ નિશ્ચિત સિન્ટેક્સને કારણે સ્ટેટિકલી એનાલિસિસ કરવા માટે સરળ છે. આ Vue ના ટેમ્પલેટ કમ્પાઇલરને વર્ચ્યુઅલ DOM ના પરફોર્મન્સને સુધારવા માટે ઘણા કમ્પાઇલ-ટાઇમ ઓપ્ટિમાઇઝેશન લાગુ કરવાની મંજૂરી આપે છે (જેની આપણે નીચે ચર્ચા કરીશું).

વ્યવહારમાં, એપ્લિકેશન્સમાં મોટાભાગના ઉપયોગના કેસો માટે ટેમ્પલેટ્સ પૂરતા છે. રેન્ડર ફંક્શન્સ સામાન્ય રીતે ફક્ત તે જ રિયાઝેબલ ઘટકોમાં ઉપયોગમાં લેવાય છે કે જેમને અત્યંત ડાયનેમિક રેન્ડરિંગ લોજિક સાથે વ્યવહાર કરવાની જરૂર હોય છે. રેન્ડર ફંક્શન વપરાશ વિશે Render Functions & JSX માં વધુ વિગતવાર ચર્ચા કરવામાં આવી છે.

કમ્પાઇલર-ઇન્ફોર્મ્ડ વર્ચ્યુઅલ DOM (Compiler-Informed Virtual DOM)

React માં વર્ચ્યુઅલ DOM અમલીકરણ અને અન્ય વર્ચ્યુઅલ-DOM અમલીકરણો શુદ્ધ રનટાઇમ છે: ડિફિંગ એલ્ગોરિધમ (reconciliation algorithm) ઇનકમિંગ વર્ચ્યુઅલ DOM ટ્રી વિશે કોઈ ધારણાઓ કરી શકતું નથી, તેથી તેણે સંપૂર્ણપણે ટ્રી ને નેવિગેટ કરવું પડે છે અને દરેક vnode ના પ્રોપ્સને ડિફ (diff) કરવા પડે છે જેથી સત્યતા સુનિશ્ચિત થઈ શકે. વધારામાં, જો ટ્રીનો કોઈ ભાગ ક્યારેય બદલાતો નથી, તો પણ દરેક રિ-રેન્ડર પર તેમના માટે નવા vnodes હંમેશા બનાવવામાં આવે છે, જેના પરિણામે બિનજરૂરી મેમરી પ્રેશર આવે છે. વર્ચ્યુઅલ DOM નો આ સૌથી વધુ ટીકા કરાયેલો પાસું છે: આ બ્રુટ-ફોર્સ રિકોન્સિલેશન પ્રક્રિયા ડિક્લેરેટિવનેસ અને સચ્ચાઈના ખર્ચે કાર્યક્ષમતાનો ત્યાગ કરે છે.

પરંતુ તે આ રીતે હોવું જરૂરી નથી. Vue માં, ફ્રેમવર્ક કમ્પાઇલર અને રનટાઇમ બંનેને નિયંત્રિત કરે છે. આ અમને ઘણા કમ્પાઇલ-ટાઇમ ઓપ્ટિમાઇઝેશન લાગુ કરવાની મંજૂરી આપે છે જેનો લાભ માત્ર ટાઇટલી-કપલ્ડ (tightly-coupled) રેન્ડરર જ લઈ શકે છે. કમ્પાઇલર સ્ટેટિકલી ટેમ્પલેટનું વિશ્લેષણ કરી શકે છે અને જનરેટેડ કોડમાં સંકેતો (hints) છોડી શકે છે જેથી કરીને રનટાઇમ જ્યારે પણ શક્ય હોય ત્યારે શોર્ટકટ્સ લઈ શકે. સાથે જ, અમે હજુ પણ યુઝર માટે એજ કેસોમાં વધુ સીધા નિયંત્રણ માટે રેન્ડર ફંક્શન લેયર પર પાછા જવાની ક્ષમતા જાળવી રાખીએ છીએ. અમે આ મિશ્ર અભિગમને કમ્પાઇલર-ઇન્ફોર્મ્ડ વર્ચ્યુઅલ DOM (Compiler-Informed Virtual DOM) કહીએ છીએ.

નીચે, અમે વર્ચ્યુઅલ DOM ના રનટાઇમ પરફોર્મન્સને સુધારવા માટે Vue ટેમ્પલેટ કમ્પાઇલર દ્વારા કરવામાં આવેલા કેટલાક મુખ્ય ઓપ્ટિમાઇઝેશનની ચર્ચા કરીશું.

સ્ટેટિક કેશીંગ (Cache Static)

ઘણી વાર ટેમ્પલેટમાં એવા ભાગો હશે જેમાં કોઈ ડાયનેમિક બાઇન્ડિંગ્સ નથી:

template
<div>
  <div>foo</div> <!-- કેશ્ડ (cached) -->
  <div>bar</div> <!-- કેશ્ડ (cached) -->
  <div>{{ dynamic }}</div>
</div>

Template Explorer માં તપાસો

foo અને bar ડિવ્સ (divs) સ્ટેટિક છે - દરેક રિ-રેન્ડર પર vnodes ફરીથી બનાવવા અને તેમને ડિફ કરવા બિનજરૂરી છે. રેન્ડરર પ્રારંભિક રેન્ડર દરમિયાન આ vnodes બનાવે છે, તેમને કેશ કરે છે અને દરેક અનુગામી રિ-રેન્ડર માટે સમાન vnodes નો ઉપયોગ કરે છે. જ્યારે રેન્ડરર નોંધે છે કે જૂનો vnode અને નવો vnode એક જ છે ત્યારે તે તેમના ડિફિંગને સંપૂર્ણપણે છોડી દેવા સક્ષમ છે.

વધારામાં, જ્યારે પૂરતા પ્રમાણમાં ક્રમિક સ્ટેટિક એલિમેન્ટ્સ હોય છે, ત્યારે તેને એક સિંગલ "સ્ટેટિક vnode" માં ઘટાડવામાં આવશે જે આ તમામ નોડ્સ માટે સાદા HTML સ્ટ્રિંગ ધરાવે છે (ઉદાહરણ). આ સ્ટેટિક vnodes ને સીધા જ innerHTML સેટ કરીને માઉન્ટ કરવામાં આવે છે.

પેચ ફ્લેગ્સ (Patch Flags)

ડાયનેમિક બાઇન્ડિંગ્સવાળા સિંગલ એલિમેન્ટ માટે, આપણે કમ્પાઇલ સમયે તેમાંથી ઘણી બધી માહિતી મેળવી શકીએ છીએ:

template
<!-- ફક્ત ક્લાસ બાઇન્ડિંગ -->
<div :class="{ active }"></div>

<!-- ફક્ત id અને value બાઇન્ડિંગ્સ -->
<input :id="id" :value="value">

<!-- ફક્ત ટેક્સ્ટ ચિલ્ડ્રન -->
<div>{{ dynamic }}</div>

Template Explorer માં તપાસો

આ એલિમેન્ટ્સ માટે રેન્ડર ફંક્શન કોડ જનરેટ કરતી વખતે, Vue તે ડાયનેમિક બાઇન્ડિંગને vnode બનાવવાના કોલ (creation call) માં સીધો એન્કોડ કરે છે:

js
createElementVNode("div", {
  class: _normalizeClass({ active: _ctx.active })
}, null, 2 /* CLASS */)

છેલ્લી વેલ્યુ, 2, એ પેચ ફ્લેગ (patch flag) છે. એક એલિમેન્ટમાં બહુવિધ પેચ ફ્લેગ્સ હોઈ શકે છે, જે એક જ નંબરમાં મર્જ કરવામાં આવશે. રનટાઇમ રેન્ડરર પછી બિટવાઇઝ ઓપરેશન્સ (bitwise operations) નો ઉપયોગ કરીને ફ્લેગ્સ તપાસી શકે છે કે તેણે કોઈ ચોક્કસ કામ કરવાની જરૂર છે કે નહીં:

js
if (vnode.patchFlag & PatchFlags.CLASS /* 2 */) {
  // એલિમેન્ટનો ક્લાસ અપડેટ કરો
}

બિટવાઇઝ ચેક્સ અત્યંત ઝડપી છે. પેચ ફ્લેગ્સ સાથે, Vue ડાયનેમિક બાઇન્ડિંગ્સ સાથે એલિમેન્ટ્સને અપડેટ કરતી વખતે જરૂરી ન્યૂનતમ કામ કરવા સક્ષમ છે.

Vue એ પણ એન્કોડ કરે છે કે vnode પાસે કયા પ્રકારના બાળકો (children) છે. ઉદાહરણ તરીકે, જે ટેમ્પલેટમાં બહુવિધ રૂટ નોડ્સ હોય છે તે ફ્રેગમેન્ટ (fragment) તરીકે દર્શાવવામાં આવે છે. મોટા ભાગના કિસ્સાઓમાં, આપણે ખાતરીપૂર્વક જાણીએ છીએ કે આ રૂટ નોડ્સનો ક્રમ ક્યારેય બદલાશે નહીં, તેથી આ માહિતી રનટાઇમને પેચ ફ્લેગ તરીકે પણ આપી શકાય છે:

js
export function render() {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    /* children */
  ], 64 /* STABLE_FRAGMENT */))
}

આમ રનટાઇમ રૂટ ફ્રેગમેન્ટ માટે ચાઇલ્ડ-ઓર્ડર રિ-કોન્સિલેશન (reconciliation) ને સંપૂર્ણપણે છોડી શકે છે.

ટ્રી ફ્લેટનિંગ (Tree Flattening)

અગાઉના ઉદાહરણમાંથી જનરેટ થયેલ કોડ પર ફરી એક નજર નાખતા, તમે નોંધશો કે પરત કરેલા વર્ચ્યુઅલ DOM ટ્રીનો રૂટ એક વિશિષ્ટ createElementBlock() કોલનો ઉપયોગ કરીને બનાવવામાં આવ્યો છે:

js
export function render() {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    /* children */
  ], 64 /* STABLE_FRAGMENT */))
}

કન્સેપ્ટ મુજબ, એક "બ્લોક (block)" એ ટેમ્પલેટનો એક ભાગ છે જેમાં સ્થિર આંતરિક બંધારણ (inner structure) હોય છે. આ કિસ્સામાં, સમગ્ર ટેમ્પલેટમાં એક જ બ્લોક છે કારણ કે તેમાં v-if અને v-for જેવા કોઈ સ્ટ્રક્ચરલ ડાયરેક્ટિવ્સ નથી.

દરેક બ્લોક કોઈપણ વંશજ (descendant) નોડ્સ (માત્ર સીધા બાળકો જ નહીં) જે પેચ ફ્લેગ્સ ધરાવે છે તેને ટ્રેક કરે છે. ઉદાહરણ તરીકે:

template
<div> <!-- રૂટ બ્લોક -->
  <div>...</div>         <!-- ટ્રેક નથી -->
  <div :id="id"></div>   <!-- ટ્રેક કરેલ છે -->
  <div>                  <!-- ટ્રેક નથી -->
    <div>{{ bar }}</div> <!-- ટ્રેક કરેલ છે -->
  </div>
</div>

પરિણામ એક ફ્લેટન (flattened) એરે છે જેમાં ફક્ત ડાયનેમિક વંશજ નોડ્સ હોય છે:

div (block root)
- :id બાઇન્ડિંગ સાથે div
- {{ bar }} બાઇન્ડિંગ સાથે div

જ્યારે આ કમ્પોનન્ટને ફરીથી રેન્ડર કરવાની જરૂર હોય, ત્યારે તેણે આખા ટ્રી ને બદલે માત્ર ફ્લેટન ટ્રી દ્વારા જ ચાલવાની જરૂર છે. આને ટ્રી ફ્લેટનિંગ (Tree Flattening) કહેવામાં આવે છે, અને તે વર્ચ્યુઅલ DOM રિકોન્સિલેશન દરમિયાન પાર કરવા માટે જરૂરી નોડ્સની સંખ્યામાં ઘણો ઘટાડો કરે છે. ટેમ્પલેટના કોઈપણ સ્ટેટિક ભાગો અસરકારક રીતે છોડી દેવામાં આવે છે.

v-if અને v-for ડાયરેક્ટિવ્સ નવા બ્લોક નોડ્સ બનાવશે:

template
<div> <!-- રૂટ બ્લોક -->
  <div>
    <div v-if> <!-- જો કે (if block) -->
      ...
    </div>
  </div>
</div>

ચાઇલ્ડ બ્લોક પેરેન્ટ બ્લોકના ડાયનેમિક વંશજોના એરેની અંદર ટ્રેક કરવામાં આવે છે. આ પેરેન્ટ બ્લોક માટે સ્થિર માળખું જાળવી રાખે છે.

SSR હાઇડ્રેશન પર અસર (Impact on SSR Hydration)

પેચ ફ્લેગ્સ અને ટ્રી ફ્લેટનિંગ બંને Vue ના SSR Hydration પર્ફોર્મન્સમાં પણ ઘણો સુધારો કરે છે:

  • સિંગલ એલિમેન્ટ હાઇડ્રેશન સંબંધિત vnode ના પેચ ફ્લેગના આધારે ઝડપી રીતો અપનાવી શકે છે.

  • હાઇડ્રેશન દરમિયાન માત્ર બ્લોક નોડ્સ અને તેમના ડાયનેમિક વંશજોને જ પાર કરવાની જરૂર છે, અસરકારક રીતે ટેમ્પલેટ સ્તરે આંશિક હાઇડ્રેશન (partial hydration) પ્રાપ્ત કરે છે.

રેન્ડરિંગ મિકેનિઝમ (Rendering Mechanism) has loaded