સર્વર-સાઇડ રેન્ડરિંગ (Server-Side Rendering - SSR)
વિહંગાવલોકન (Overview)
SSR શું છે? (What is SSR?)
Vue.js એ ક્લાયન્ટ-સાઇડ એપ્લિકેશન્સ બનાવવા માટેનું માળખું (framework) છે. ડિફોલ્ટ રૂપે, Vue ઘટકો આઉટપુટ તરીકે બ્રાઉઝરમાં DOM બનાવે છે અને તેમાં ફેરફાર કરે છે. જો કે, સર્વર પર HTML સ્ટ્રિંગ્સમાં સમાન ઘટકોને રેન્ડર કરવા, તેમને સીધા બ્રાઉઝર પર મોકલવા અને છેલ્લે ક્લાયન્ટ પર સંપૂર્ણ ઇન્ટરેક્ટિવ એપ્લિકેશનમાં સ્ટેટિક માર્કઅપને "હાઇડ્રેટ (hydrate)" કરવાનું પણ શક્ય છે.
સર્વર-રેન્ડર્ડ Vue.js એપ્લિકેશનને "આઇસોમોર્ફિક (isomorphic)" અથવા "યુનિવર્સલ (universal)" પણ ગણી શકાય, તે અર્થમાં કે તમારી એપ્લિકેશનનો મોટાભાગનો કોડ સર્વર અને ક્લાયન્ટ બંને પર ચાલે છે.
SSR શા માટે? (Why SSR?)
ક્લાયન્ટ-સાઇડ સિંગલ-પેજ એપ્લિકેશન (SPA) ની તુલનામાં, SSR ના ફાયદા મુખ્યત્વે આમાં રહેલા છે:
ઝડપી ટાઇમ-ટુ-કન્ટેન્ટ (Faster time-to-content): આ ધીમા ઈન્ટરનેટ અથવા ધીમા ઉપકરણો પર વધુ પ્રબળ છે. સર્વર-રેન્ડર્ડ માર્કઅપ પ્રદર્શિત કરવા માટે તમામ JavaScript ડાઉનલોડ અને એક્ઝિક્યુટ ન થાય ત્યાં સુધી રાહ જોવાની જરૂર નથી, તેથી તમારા વપરાશકર્તાને સંપૂર્ણ રીતે રેન્ડર કરેલું પેજ વહેલું દેખાશે. વધારામાં, ડેટા મેળવવાનું (data fetching) પ્રારંભિક મુલાકાત માટે સર્વર-સાઇડ પર કરવામાં આવે છે, જે સંભવિતપણે ક્લાયંટ કરતાં તમારા ડેટાબેઝ સાથે ઝડપી જોડાણ ધરાવે છે. આ સામાન્ય રીતે સુધારેલા Core Web Vitals મેટ્રિક્સ, બહેતર વપરાશકર્તા અનુભવમાં પરિણમે છે અને તે એપ્લિકેશન્સ માટે જટિલ હોઈ શકે છે જ્યાં ટાઇમ-ટુ-કન્ટેન્ટ સીધી રીતે કન્વર્ઝન રેટ (conversion rate) સાથે સંકળાયેલ છે.
યુનિફાઇડ મેન્ટલ મોડલ (Unified mental model): બેકએન્ડ ટેમ્પલેટિંગ સિસ્ટમ અને ફ્રન્ટએન્ડ ફ્રેમવર્ક વચ્ચે આમતેમ કૂદવાને બદલે તમારે તમારી આખી એપ વિકસાવવા માટે સમાન ભાષા અને સમાન ડિક્લેરેટિવ, ઘટક-લક્ષી મેન્ટલ મોડલનો ઉપયોગ કરવાનો મળે છે.
વધુ સારું SEO: સર્ચ એન્જિન ક્રોલર્સ સીધા જ સંપૂર્ણ રેન્ડર થયેલ પેજ જોશે.
TIP
અત્યાર સુધી, Google અને Bing સિંક્રનસ (synchronous) JavaScript એપ્લિકેશનને બરાબર ઇન્ડેક્સ કરી શકે છે. સિંક્રનસ (Synchronous) એ ત્યાં મુખ્ય શબ્દ છે. જો તમારી એપ્લિકેશન લોડિંગ સ્પિનરથી શરૂ થાય છે, પછી Ajax દ્વારા સામગ્રી મેળવે છે, તો ક્રોલર તમારા સમાપ્ત થવાની રાહ જોશે નહીં. આનો અર્થ એ છે કે જો તમારી પાસે SEO મહત્વપૂર્ણ હોય તેવા પેજીસ પર અસિંક્રનસલી (asynchronously) મેળવેલ સામગ્રી છે, તો SSR જરૂરી હોઈ શકે છે.
SSR નો ઉપયોગ કરતી વખતે ધ્યાનમાં લેવાના કેટલાક ટ્રેડ-ઓફ (trade-offs) પણ છે:
ડેવલપમેન્ટ મર્યાદાઓ. બ્રાઉઝર-વિશિષ્ટ કોડનો ઉપયોગ ફક્ત અમુક લાઇફસાયકલ હૂક્સની અંદર જ થઈ શકે છે; કેટલીક બાહ્ય લાઇબ્રેરીઓને સર્વર-રેન્ડર્ડ એપ્લિકેશનમાં ચલાવવા માટે સક્ષમ થવા માટે ખાસ ટ્રીટમેન્ટની જરૂર પડી શકે છે.
વધુ સામેલ બિલ્ડ સેટઅપ અને ડિપ્લોયમેન્ટ આવશ્યકતાઓ. સંપૂર્ણ સ્ટેટિક SPA થી વિપરીત કે જે કોઈપણ સ્ટેટિક ફાઇલ સર્વર પર ડિપ્લોય કરી શકાય છે, સર્વર-રેન્ડર્ડ એપ્લિકેશન માટે એવા વાતાવરણની જરૂર છે જ્યાં Node.js સર્વર ચાલી શકે.
વધુ સર્વર-સાઇડ લોડ. Node.js માં આખી એપ રેન્ડર કરવી એ માત્ર સ્ટેટિક ફાઇલો પ્રદાન કરવા કરતા વધુ CPU-ઇન્ટેન્સિવ હોવાનું છે, તેથી જો તમે વધુ ટ્રાફિકની અપેક્ષા રાખો છો, તો અનુરૂપ સર્વર લોડ માટે તૈયાર રહો અને સમજદારીપૂર્વક કેશિંગ (caching) વ્યૂહરચનાનો ઉપયોગ કરો.
તમારી એપ્લિકેશન માટે SSR નો ઉપયોગ કરતા પહેલા, તમારે જે પ્રથમ પ્રશ્ન પૂછવો જોઈએ તે એ છે કે શું તમારે ખરેખર તેની જરૂર છે. તે મોટે ભાગે તમારી એપ્લિકેશન માટે ટાઇમ-ટુ-કન્ટેન્ટ કેટલું મહત્વનું છે તેના પર નિર્ભર છે. ઉદાહરણ તરીકે, જો તમે આંતરિક ડેશબોર્ડ બનાવી રહ્યા છો જ્યાં પ્રારંભિક લોડ પર વધારાની થોડીક સો મિલિસેકન્ડ્સથી કોઈ ફરક પડતો નથી, તો SSR અતિશય (overkill) હશે. જો કે, એવા કિસ્સાઓમાં કે જ્યાં ટાઇમ-ટુ-કન્ટેન્ટ એકદમ જટિલ છે, SSR તમને શ્રેષ્ઠ સંભવિત પ્રારંભિક લોડ પ્રદર્શન પ્રાપ્ત કરવામાં મદદ કરી શકે છે.
SSR વિરુદ્ધ SSG (SSR vs. SSG)
સ્ટેટિક સાઇટ જનરેશન (Static Site Generation - SSG), જેને પ્રી-રેન્ડરિંગ (pre-rendering) તરીકે પણ ઓળખવામાં આવે છે, તે ઝડપી વેબસાઇટ્સ બનાવવા માટેની અન્ય લોકપ્રિય તકનીક છે. જો પેજને સર્વર-રેન્ડર કરવા માટે જરૂરી ડેટા દરેક વપરાશકર્તા માટે સમાન હોય, તો દરેક વખતે વિનંતી આવે ત્યારે પેજ રેન્ડર કરવાને બદલે, અમે તેને બિલ્ડ પ્રક્રિયા દરમિયાન અગાઉથી માત્ર એક જ વાર રેન્ડર કરી શકીએ છીએ. પ્રી-રેન્ડર્ડ પેજીસ જનરેટ કરવામાં આવે છે અને સ્ટેટિક HTML ફાઇલો તરીકે સર્વ કરવામાં આવે છે.
SSG એ SSR એપ્સની જેમ જ પ્રદર્શન લાક્ષણિકતાઓ જાળવી રાખે છે: તે ઉત્તમ ટાઇમ-ટુ-કન્ટેન્ટ પ્રદર્શન પ્રદાન કરે છે. તે જ સમયે, તે SSR એપ્સ કરતા સસ્તું અને ડિપ્લોય કરવામાં સરળ છે કારણ કે આઉટપુટ સ્ટેટિક HTML અને એસેટ્સ છે. અહીં મુખ્ય શબ્દ સ્ટેટિક (static) છે: SSG માત્ર સ્ટેટિક ડેટા પૂરો પાડતા પેજીસ પર જ લાગુ કરી શકાય છે, એટલે કે ડેટા જે બિલ્ડ સમયે જાણીતો હોય છે અને વિનંતીઓ (requests) વચ્ચે બદલાઈ શકતો નથી. જ્યારે પણ ડેટા બદલાય છે, ત્યારે નવા ડિપ્લોયમેન્ટની જરૂર પડે છે.
જો તમે મુઠ્ઠીભર માર્કેટિંગ પેજીસ (દા.ત. /, /about, /contact, વગેરે) ના SEO ને સુધારવા માટે માત્ર SSR ની તપાસ કરી રહ્યા હોવ, તો કદાચ તમે SSR ને બદલે SSG ઇચ્છી શકો છો. SSG કન્ટેન્ટ-આધારિત વેબસાઇટ્સ જેમ કે ડોક્યુમેન્ટેશન સાઇટ્સ અથવા બ્લોગ્સ માટે પણ ઉત્તમ છે. હકીકતમાં, તમે અત્યારે જે વેબસાઇટ વાંચી રહ્યા છો તે VitePress નો ઉપયોગ કરીને સ્ટેટિક રીતે જનરેટ કરવામાં આવી છે, જે Vue-સંચાલિત સ્ટેટિક સાઇટ જનરેટર છે.
મૂળભૂત ટ્યુટોરીયલ (Basic Tutorial)
એપ રેન્ડર કરવી (Rendering an App)
ચાલો Vue SSR ના સૌથી મૂળભૂત ઉદાહરણ પર એક નજર કરીએ.
૧. નવી ડિરેક્ટરી બનાવો અને તેમાં cd કરો. ૨. npm init -y ચલાવો. ૩. package.json માં "type": "module" ઉમેરો જેથી Node.js ES modules mode માં ચાલે. ૪. npm install vue ચલાવો. ૫. એક example.js ફાઇલ બનાવો:
js
// આ સર્વર પર Node.js માં ચાલે છે.
import { createSSRApp } from 'vue'
// Vue ની server-rendering API `vue/server-renderer` હેઠળ એક્સપોઝ થયેલ છે.
import { renderToString } from 'vue/server-renderer'
const app = createSSRApp({
data: () => ({ count: 1 }),
template: `<button @click="count++">{{ count }}</button>`
})
renderToString(app).then((html) => {
console.log(html)
})પછી ચલાવો:
sh
> node example.jsતેણે કમાન્ડ લાઇન પર નીચે મુજબ પ્રિન્ટ કરવું જોઈએ:
<button>1</button>renderToString() Vue એપ્લિકેશન ઇન્સ્ટન્સ લે છે અને એક પ્રોમિસ આપે છે જે એપ્લિકેશનના રેન્ડર કરેલા HTML માં રિઝોલ્વ થાય છે. Node.js Stream API અથવા Web Streams API નો ઉપયોગ કરીને સ્ટ્રીમ રેન્ડરિંગ (stream rendering) પણ શક્ય છે. સંપૂર્ણ વિગતો માટે SSR API રિફરન્સ તપાસો.
પછી અમે Vue SSR કોડને સર્વર રિક્વેસ્ટ હેન્ડલરમાં ખસેડી શકીએ છીએ, જે સંપૂર્ણ પેજ HTML સાથે એપ્લિકેશન માર્કઅપને લપેટી દે છે. અમે આગામી પગલાઓ માટે express નો ઉપયોગ કરીશું:
npm install expressચલાવો.- નીચેની
server.jsફાઇલ બનાવો:
js
import express from 'express'
import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'
const server = express()
server.get('/', (req, res) => {
const app = createSSRApp({
data: () => ({ count: 1 }),
template: `<button @click="count++">{{ count }}</button>`
})
renderToString(app).then((html) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Vue SSR ઉદાહરણ</title>
</head>
<body>
<div id="app">${html}</div>
</body>
</html>
`)
})
})
server.listen(3000, () => {
console.log('તૈયાર (ready)')
})છેલ્લે, node server.js ચલાવો અને http://localhost:3000 ની મુલાકાત લો. તમારે પેજ બટન સાથે કામ કરતું જોવું જોઈએ.
ક્લાયન્ટ હાઇડ્રેશન (Client Hydration)
જો તમે બટન પર ક્લિક કરશો, તો તમે નોંધશો કે નંબર બદલાતો નથી. ક્લાયન્ટ પર HTML સંપૂર્ણપણે સ્ટેટિક છે કારણ કે અમે બ્રાઉઝરમાં Vue લોડ કરી રહ્યાં નથી.
ક્લાયન્ટ-સાઇડ એપ્લિકેશનને ઇન્ટરેક્ટિવ (interactive) બનાવવા માટે, Vue એ હાઇડ્રેશન (hydration) સ્ટેપ કરવાની જરૂર છે. હાઇડ્રેશન દરમિયાન, તે સમાન Vue એપ્લિકેશન બનાવે છે જે સર્વર પર ચલાવવામાં આવી હતી, દરેક ઘટકને તે જે DOM નોડ્સને નિયંત્રિત કરવા જોઈએ તેની સાથે મેચ કરે છે અને DOM ઇવેન્ટ લિસનર્સ જોડે છે.
હાઇડ્રેશન મોડમાં એપ માઉન્ટ કરવા માટે, આપણે createApp() ને બદલે createSSRApp() નો ઉપયોગ કરવાની જરૂર છે:
js
// આ બ્રાઉઝરમાં ચાલે છે.
import { createSSRApp } from 'vue'
const app = createSSRApp({
// ...સર્વર જેવી જ એપ
})
// ક્લાયન્ટ પર SSR એપ્લિકેશનને માઉન્ટ કરવાનું એ ધારે છે
// કે HTML પ્રી-રેન્ડર હતું અને નવા DOM નોડ્સ માઉન્ટ કરવાને બદલે
// હાઇડ્રેશન કરશે.
app.mount('#app')કોડ સ્ટ્રક્ચર (Code Structure)
નોંધ લો કે કેવી રીતે આપણે સર્વર પરની જેમ જ એપ્લિકેશન અમલીકરણનો ફરીથી ઉપયોગ કરવાની જરૂર છે. આ તે છે જ્યાં આપણે SSR એપ્લિકેશનમાં કોડ સ્ટ્રક્ચર વિશે વિચારવાનું શરૂ કરવાની જરૂર છે - આપણે સર્વર અને ક્લાયન્ટ વચ્ચે સમાન એપ્લિકેશન કોડ કેવી રીતે શેર કરી શકીએ?
અહીં અમે સૌથી મૂળભૂત સેટઅપનું નિદર્શન કરીશું. સૌપ્રથમ, ચાલો એપ્લિકેશન નિર્માણ તર્કને સમર્પિત ફાઇલ, app.js માં વિભાજીત કરીએ:
js
// (સર્વર અને ક્લાયંટ વચ્ચે શેર કરેલ)
import { createSSRApp } from 'vue'
export function createApp() {
return createSSRApp({
data: () => ({ count: 1 }),
template: `<button @click="count++">{{ count }}</button>`
})
}આ ફાઇલ અને તેની ડિપેન્ડન્સીસ સર્વર અને ક્લાયન્ટ વચ્ચે શેર કરવામાં આવે છે - અમે તેમને યુનિવર્સલ કોડ (universal code) કહીએ છીએ. જ્યારે તમે યુનિવર્સલ કોડ લખો ત્યારે તમારે સંખ્યાબંધ બાબતો પર ધ્યાન આપવાની જરૂર છે, જેમ કે આપણે નીચે ચર્ચા કરીશું.
આપણો ક્લાયન્ટ એન્ટ્રી પોઈન્ટ યુનિવર્સલ કોડ ઇમ્પોર્ટ કરે છે, એપ બનાવે છે અને માઉન્ટ કરે છે:
js
import { createApp } from './app.js'
createApp().mount('#app')અને સર્વર રિક્વેસ્ટ હેન્ડપલરમાં સમાન એપ્લિકેશન નિર્માણ લોજિક (logic) નો ઉપયોગ કરે છે:
js
// (અસંબંધિત કોડ અવગણ્યો છે)
import { createApp } from './app.js'
server.get('/', (req, res) => {
const app = createApp()
renderToString(app).then(html => {
// ...
})
})વધારામાં, બ્રાઉઝરમાં ગ્રાહક ફાઇલો લોડ કરવા માટે, આપણે આની પણ જરૂર છે:
૧. server.js માં server.use(express.static('.')) ઉમેરીને ક્લાયન્ટ ફાઇલો સર્વ કરો. ૨. HTML શેલમાં <script type="module" src="/client.js"></script> ઉમેરીને ક્લાયન્ટ એન્ટ્રી લોડ કરો. ૩. HTML શેલમાં Import Map ઉમેરીને બ્રાઉઝરમાં import * from 'vue' જેવા વપરાશને સપોર્ટ કરો.
StackBlitz પર પૂર્ણ થયેલ ઉદાહરણ અજમાવી જુઓ. બટન હવે ઇન્ટરેક્ટિવ છે!
હાયર લેવલ સોલ્યુશન્સ (Higher Level Solutions)
ઉદાહરણ પરથી પ્રોડક્શન-રેડી SSR એપમાં જવા માટે ઘણું બધું સામેલ છે. અમારે આની જરૂર પડશે:
Vue SFCs અને અન્ય બિલ્ડ સ્ટેપ જરૂરિયાતોને સપોર્ટ કરો. હકીકતમાં, અમારે સમાન એપ્લિકેશન માટે બે બિલ્ડ્સનું સંકલન કરવાની જરૂર પડશે: એક ક્લાયન્ટ માટે અને એક સર્વર માટે.
TIP
Vue ઘટકો જ્યારે SSR માટે ઉપયોગમાં લેવાય છે ત્યારે અલગ રીતે કમ્પાઇલ કરવામાં આવે છે - ટેમ્પલેટ્સ વધુ કાર્યક્ષમ રેન્ડરિંગ પ્રદર્શન માટે વર્ચ્યુઅલ DOM રેન્ડર ફંક્શન્સને બદલે સ્ટ્રિંગ કોન્કેટેનેશન (concatenations) માં સંકલિત કરવામાં આવે છે.
સર્વર રિક્વેસ્ટ હેન્ડલરમાં, સાચી ક્લાયન્ટ-સાઇડ એસેટ લિંક્સ અને શ્રેષ્ઠ સંસાધન સંકેતો (resource hints) સાથે HTML રેન્ડર કરો. અમારે SSR અને SSG મોડ વચ્ચે સ્વિચ કરવાની અથવા સમાન એપ્લિકેશનમાં બંનેને મિશ્રિત કરવાની પણ જરૂર પડી શકે છે.
રાઉટીંગ, ડેટા ફેચિંગ અને સ્ટેટ મેનેજમેન્ટ સ્ટોર્સને યુનિવર્સલ રીતે મેનેજ કરો.
સંપૂર્ણ અમલીકરણ તદ્દન જટિલ હશે અને તમે જે કામ કરવાનું પસંદ કર્યું છે તે બિલ્ડ ટૂલચેન પર આધાર રાખે છે. તેથી, અમે હાયર-લેવલના સોલ્યુશન સાથે જવાની ભારપૂર્વક ભલામણ કરીએ છીએ જે તમારા માટે જટિલતાને દૂર કરે છે. નીચે અમે Vue ઇકોસિસ્ટમમાં થોડા ભલામણ કરેલ SSR સોલ્યુશન્સ રજૂ કરીશું.
Nuxt
Nuxt એ Vue ઇકોસિસ્ટમની ટોચ પર બનેલું ઉચ્ચ સ્તરનું માળખું છે જે યુનિવર્સલ Vue એપ્લિકેશન્સ લખવા માટે સુવ્યવસ્થિત ડેવલપમેન્ટ અનુભવ પ્રદાન કરે છે. વધુ સારું, તમે તેને સ્ટેટિક સાઇટ જનરેટર તરીકે પણ વાપરી શકો છો! અમે તેને અજમાવી જોવાની ભારપૂર્વક ભલામણ કરીએ છીએ.
Quasar
Quasar એ સંપૂર્ણ Vue-આધારિત સોલ્યુશન છે જે તમને SPA, SSR, PWA, મોબાઇલ એપ, ડેસ્કટોપ એપ અને બ્રાઉઝર એક્સ્ટેંશનને એક કોડબેઝનો ઉપયોગ કરીને લક્ષ્ય બનાવવાની મંજૂરી આપે છે. તે માત્ર બિલ્ડ સેટઅપને જ હેન્ડલ કરતું નથી, પરંતુ મટીરીયલ ડિઝાઇન સુસંગત UI ઘટકોનો સંપૂર્ણ સંગ્રહ પણ પૂરો પાડે છે.
Vite SSR
Vite Vue સર્વર-સાઇડ રેન્ડરિંગ માટે બિલ્ટ-ઇન સપોર્ટ (support for Vue server-side rendering) પૂરો પાડે છે, પરંતુ તે જાણી જોઈને લો-લેવલ છે. જો તમે સીધા Vite સાથે જવા માંગતા હોવ, તો vite-plugin-ssr તપાસો, જે એક સમુદાય પ્લગિન છે જે તમારા માટે ઘણી પડકારજનક વિગતોને દૂર કરે છે.
તમે મેન્યુઅલ સેટઅપનો ઉપયોગ કરીને અહીં ઉદાહરણ Vue + Vite SSR પ્રોજેક્ટ પણ શોધી શકો છો, જે આગળ વધવા માટેના આધાર તરીકે કામ કરી શકે છે. નોંધ કરો કે જો તમે SSR / બિલ્ડ ટૂલ્સમાં અનુભવી હોવ અને ખરેખર હાયર-લેવલના આર્કિટેક્ચર પર સંપૂર્ણ નિયંત્રણ રાખવા માંગતા હોવ તો જ આની ભલામણ કરવામાં આવે છે.
SSR-ફ્રેન્ડલી કોડ લખવો (Writing SSR-friendly Code)
તમારા બિલ્ડ સેટઅપ અથવા હાયર-લેવલના ફ્રેમવર્કની પસંદગીને ધ્યાનમાં લીધા વિના, કેટલીક પ્રણાલીઓ છે જે તમામ Vue SSR એપ્લિકેશન્સમાં લાગુ પડે છે.
સર્વર પર રિએક્ટિવિટી (Reactivity on the Server)
SSR દરમિયાન, દરેક રિક્વેસ્ટ URL આપણી એપ્લિકેશનની ઇચ્છિત સ્થિતિ (state) સાથે મેપ થાય છે. વપરાશકર્તાની કોઈ ક્રિયાપ્રતિક્રિયા નથી અને કોઈ DOM અપડેટ નથી, તેથી સર્વર પર રિએક્ટિવિટી બિનજરૂરી છે. ડિફોલ્ટ રૂપે, બહેતર પ્રદર્શન માટે SSR દરમિયાન રિએક્ટિવિટી અક્ષમ કરવામાં આવે છે.
કમ્પોનન્ટ લાઇફસાયકલ હૂક્સ (Component Lifecycle Hooks)
ક્યારથી કોઈ ડાયનેમિક અપડેટ્સ નથી, લાઇફસાયકલ હૂક્સ જેમ કે onMounted અથવા onUpdated SSR દરમિયાન કૉલ કરવામાં આવશે નહીં અને તે ફક્ત ક્લાયન્ટ પર જ ચલાવવામાં આવશે.
તમારે એવા કોડ ટાળવા જોઈએ જે આડઅસરો (side effects) પેદા કરે છે જેને setup() અથવા <script setup> ના રૂટ સ્કોપ માં ક્લીનઅપની જરૂર હોય છે. આવી આડઅસરોનું ઉદાહરણ setInterval સાથે ટાઈમર સેટ કરવું છે. માત્ર ક્લાયન્ટ-સાઇડ કોડમાં આપણે ટાઈમર સેટઅપ કરી શકીએ છીએ અને પછી તેને onBeforeUnmount અથવા onUnmounted માં ફાડી શકીએ છીએ. જો કે, કારણ કે અનમાઉન્ટ હૂક્સ ક્યારેય SSR દરમિયાન બોલાવવામાં આવશે નહીં, ટાઈમર કાયમ માટે આસપાસ રહેશે. આને ટાળવા માટે, તમારા સાઇડ-ઇફેક્ટ કોડને તેના બદલે onMounted માં ખસેડો.
પ્લેટફોર્મ-વિશિષ્ટ APIs ની એક્સેસ (Access to Platform-Specific APIs)
યુનિવર્સલ કોડ પ્લેટફોર્મ-વિશિષ્ટ APIs ની એક્સેસ ધારી શકતો નથી, તેથી જો તમારો કોડ window અથવા document જેવા બ્રાઉઝર-ઓન્લી ગ્લોબલ્સનો સીધો ઉપયોગ કરે છે, તો જ્યારે Node.js માં તેને ચલાવવામાં આવે ત્યારે તેઓ એરર્સ ફેંકશે, અને ઊલટું.
સર્વર અને ક્લાયંટ વચ્ચે શેર કરવામાં આવતા કાર્યો માટે પરંતુ વિવિધ પ્લેટફોર્મ APIs સાથે, પ્લેટફોર્મ-વિશિષ્ટ અમલીકરણોને યુનિવર્સલ API ની અંદર લપેટી દેવાની અથવા આ કરનારા સોફ્ટવેર સંગ્રહો (libraries) નો ઉપયોગ કરવાની ભલામણ કરવામાં આવે છે. ઉદાહરણ તરીકે, તમે સર્વર અને ક્લાયન્ટ બંને પર સમાન ફેચ API નો ઉપયોગ કરવા માટે node-fetch નો ઉપયોગ કરી શકો છો.
માત્ર બ્રાઉઝર-ઓન્લી APIs માટે, સામાન્ય અભિગમ એ છે કે ક્લાયન્ટ-ઓન્લી લાઇફસાયકલ હૂક્સ જેમ કે onMounted ની અંદર તેમને એક્સેસ (access) કરવી.
નોંધ લો કે જો થર્ડ-પાર્ટી લાઇબ્રેરી યુનિવર્સલ વપરાશને ધ્યાનમાં રાખીને લખવામાં આવી નથી, તો તેને સર્વર-રેન્ડર્ડ એપ્લિકેશનમાં એકીકૃત કરવું મુશ્કેલ હોઈ શકે છે. તમે કેટલાક ગ્લોબલ્સની મજાક ઉડાવીને તેને કાર્યરત કરી શકશો, પરંતુ તે હેકી (hacky) હશે અને અન્ય લાઇબ્રેરીઓના પર્યાવરણ શોધ કોડમાં દખલ કરી શકે છે.
ક્રોસ-રિક્વેસ્ટ સ્ટેટ પોલ્યુશન (Cross-Request State Pollution)
સ્ટેટ મેનેજમેન્ટ પ્રકરણમાં, અમે રિએક્ટિવિટી APIs નો ઉપયોગ કરીને સાદી સ્ટેટ મેનેજમેન્ટ પેટર્ન રજૂ કરી છે. SSR સંદર્ભમાં, આ પેટર્નને કેટલાક વધારાના ગોઠવણો (adjustments) ની જરૂર છે.
પેટર્ન JavaScript મોડ્યુલના રૂટ સ્કોપમાં શેર કરેલી સ્ટેટ જાહેર કરે છે. આ તેમને સીગલટન્સ (singletons) બનાવે છે - એટલે કે આપણી એપ્લિકેશનના સમગ્ર જીવનચક્ર દરમિયાન રિએક્ટિવ ઓબ્જેક્ટનો માત્ર એક જ ઇન્સ્ટન્સ હોય છે. આ શુદ્ધ ક્લાયન્ટ-સાઇડ Vue એપ્લિકેશનમાં અપેક્ષા મુજબ કાર્ય કરે છે, કારણ કે અમારી એપ્લિકેશનના મોડ્યુલ્સ દરેક બ્રાઉઝર સેઝી મુલાકાત માટે નવેસરથી શરૂ થાય છે.
જો કે, SSR સંદર્ભમાં, જ્યારે સર્વર બુટ થાય છે ત્યારે એપ્લિકેશન મોડ્યુલ્સ સામાન્ય રીતે સર્વર પર માત્ર એક જ વાર શરૂ થાય છે. સમાન મોડ્યુલ ઇન્સ્ટન્સનો ઉપયોગ બહુવિધ સર્વર વિનંતીઓ પર કરવામાં આવશે, અને તેથી અમારા સિંગલટન સ્ટેટ ઓબ્જેક્ટ્સનો ઉપયોગ પણ કરવામાં આવશે. જો આપણે એક વપરાશકર્તા માટે વિશિષ્ટ ડેટા સાથે શેર કરેલ સિંગલટન સ્ટેટને મ્યુટેટ કરીએ છીએ, તો તે અકસ્માતે બીજા વપરાશકર્તાની વિનંતીમાં લીક થઈ શકે છે. અમે આને ક્રોસ-રિક્વેસ્ટ સ્ટેટ પોલ્યુશન (cross-request state pollution) કહીએ છીએ.
અમે તકનીકી રીતે દરેક વિનંતી પરના તમામ JavaScript મોડ્યુલ્સને ફરીથી શરૂ કરી શકીએ છીએ, જેમ આપણે બ્રાઉઝરમાં કરીએ છીએ. જો કે, JavaScript મોડ્યુલ્સને પ્રારંભ કરવું ખર્ચાળ હોઈ શકે છે, તેથી આ સર્વર કામગીરીને નોંધપાત્ર રીતે અસર કરશે.
ભલામણ કરેલ ઉકેલ એ છે કે દરેક વિનંતી પર સમગ્ર એપ્લિકેશનનો નવો ઇન્સ્ટન્સ બનાવવો - જેમાં રાઉટર અને ગ્લોબલ સ્ટોર્સનો સમાવેશ થાય છે. પછી, અમારા ઘટકોમાં તેને સીધું ઇમ્પોર્ટ કરવાને બદલે, અમે એપ-લેવલ પ્રોવાઈડ (app-level provide) નો ઉપયોગ કરીને શેર કરેલી સ્ટેટ પ્રદાન કરીએ છીએ અને જે ઘટકોમાં તેની જરૂર હોય તેમાં ઇન્જેક્ટ કરીએ છીએ:
js
// (સર્વર અને ક્લાયંટ વચ્ચે શેર કરેલ)
import { createSSRApp } from 'vue'
import { createStore } from './store.js'
// દરેક વિનંતી પર બોલાવવામાં આવે છે
export function createApp() {
const app = createSSRApp(/* ... */)
// વિનંતી દીઠ સ્ટોરનો નવો ઇન્સ્ટન્સ બનાવો
const store = createStore(/* ... */)
// એપ સ્તરે સ્ટોર પ્રદાન કરો
app.provide('store', store)
// હાઇડ્રેશન હેતુઓ માટે સ્ટોર પણ એક્સપોઝ કરો
return { app, store }
}Pinia જેવી સ્ટેટ મેનેજમેન્ટ લાઇબ્રેરીઓ આને ધ્યાનમાં રાખીને ડિઝાઇન કરવામાં આવી છે. વધુ વિગતો માટે Pinia ની SSR ગાઇડ નો સંપર્ક કરો.
હાઇડ્રેશન મિસમેચ (Hydration Mismatch)
જો પ્રી-રેન્ડર્ડ HTML નું DOM સ્ટ્રક્ચર ક્લાયન્ટ-સાઇડ એપ્લિકેશનના અપેક્ષિત આઉટપુટ સાથે મેળ ખાતું નથી, તો હાઇડ્રેશન મિસમેચ એરર આવશે. હાઇડ્રેશન મિસમેચ સામાન્ય રીતે નીચેના કારણો દ્વારા રજૂ કરવામાં આવે છે:
૧. ટેમ્પલેટમાં અમાન્ય HTML નેસ્ટિંગ સ્ટ્રક્ચર છે અને રેન્ડર કરેલ HTML બ્રાઉઝરની નેટિવ HTML પાર્સિંગ વર્તણૂક દ્વારા "સુધારેલ" છે. ઉદાહરણ તરીકે, એક સામાન્ય ભૂલ એ છે કે <div> ને <p> ની અંદર મૂકી શકાતું નથી:
html
<p><div>નમસ્તે!</div></p>જો આપણે આને અમારા સર્વર-રેન્ડર્ડ HTML માં બનાવીએ, તો જ્યારે <div> મળે ત્યારે બ્રાઉઝર પ્રથમ <p> ને સમાપ્ત કરશે અને તેને નીચેના DOM સ્ટ્રક્ચરમાં પાર્સ કરશે:
html
<p></p>
<div>નમસ્તે!</div>
<p></p>૨. રેન્ડર દરમિયાન વપરાયેલ ડેટામાં રેન્ડમલી જનરેટેડ વેલ્યુઝ હોય છે. કારણ કે સમાન એપ્લિકેશન બે વાર ચાલશે - એકવાર સર્વર પર, અને એકવાર ક્લાયન્ટ પર - રેન્ડમ વેલ્યુઝ બે રન વચ્ચે સમાન હોવાની મહાર ખાતરી નથી. રેન્ડમ-વેલ્યુ પ્રેરિત મિસમેચ ટાળવાની બે રીતો છે:
૧. v-if + onMounted નો ઉપયોગ માત્ર ક્લાયન્ટ પર જ રેન્ડમ વેલ્યુઝ પર આધાર રાખતા ભાગને રેન્ડર કરવા માટે કરો. તમારા ફ્રેમવર્કમાં આને સરળ બનાવવા માટે બિલ્ટ-ઇન સુવિધાઓ પણ હોઈ શકે છે, ઉદાહરણ તરીકે VitePress માં <ClientOnly> કમ્પોનન્ટ.
૨. રેન્ડમ નંબર જનરેટર લાઇબ્રેરીનો ઉપયોગ કરો જે સીડ્સ (seeds) સાથે જનરેટ કરવાનું સપોર્ટ કરે છે, અને ગેરંટી આપે છે કે સર્વર રન અને ક્લાયન્ટ રન સમાન સીડનો ઉપયોગ કરી રહ્યાં છે (દા.ત. ક્રમિક સ્થિતિમાં સીડનો સમાવેશ કરીને અને તેને ક્લાયન્ટ પર પુનઃપ્રાપ્ત કરીને).
૩. સર્વર અને ક્લાયન્ટ અલગ-અલગ ટાઇમ ઝોનમાં છે. કેટલીકવાર, અમે ટાઇમસ્ટેમ્પને વપરાશકર્તાના લોકલ ટાઇમમાં કન્વર્ટ કરવા માંગતા હોઈ શકીએ છીએ. જો કે, સર્વર રન દરમિયાનનો ટાઇમઝોન અને ક્લાયન્ટ રન દરમિયાનનો ટાઇમઝોન હંમેશા સરખા હોતા નથી, અને સર્વર રન દરમિયાન આપણે વપરાશકર્તાનો ટાઇમઝોન વિશ્વસનીય રીતે જાણી શકતા નથી. આવા કિસ્સાઓમાં, લોકલ ટાઇમ કન્વર્ઝન પણ ક્લાયન્ટ-ઓન્લી ઓપરેશન તરીકે થવું જોઈએ.
જ્યારે Vue હાઇડ્રેશન મિસમેચનો સામનો કરે છે, ત્યારે તે આપમેળે પુનઃપ્રાપ્ત કરવાનો અને ક્લાયન્ટ-સાઇડ સ્ટેટ સાથે મેચ કરવા માટે પ્રી-રેન્ડર્ડ DOM ને એડજસ્ટ કરવાનો પ્રયાસ કરશે. આ અયોગ્ય નોડ્સને કાઢી નાખવા અને નવા નોડ્સ માઉન્ટ કરવાને કારણે રેન્ડરિંગ પ્રદર્શનમાં થોડું નુકસાન તરફ દોરી જશે, પરંતુ મોટાભાગના કિસ્સાઓમાં, એપ અપેક્ષા મુજબ કામ કરવાનું ચાલુ રાખશે. તેમ છતાં, ડેવલપમેન્ટ દરમિયાન હાઇડ્રેશન મિસમેચને દૂર કરવું શ્રેષ્ઠ છે.
હાઇડ્રેશન મિસમેચને દબાવવું (Suppressing Hydration Mismatches)
Vue ૩.૫+ માં, data-allow-mismatch એટ્રિબ્યુટનો ઉપયોગ કરીને અનિવાર્ય હાઇડ્રેશન મિસમેચને પસંદગીયુક્ત રીતે દબાવવાનું શક્ય છે.
કસ્ટમ ડાયરેક્ટિવ્સ (Custom Directives)
ક્યારથી મોટાભાગના કસ્ટમ ડાયરેક્ટિવ્સમાં ડાયરેક્ટ DOM મેનીપ્યુલેશન સામેલ હોય છે, SSR દરમિયાન તેને અવગણવામાં આવે છે. જો કે, જો તમે નિર્દિષ્ટ કરવા માંગો છો કે કસ્ટમ ડાયરેક્ટિવ કેવી રીતે રેન્ડર થવો જોઈએ (એટલે કે તે રેન્ડર કરેલા ઘટકમાં કયા એટ્રિબ્યુટ્સ ઉમેરવા જોઈએ), તો તમે getSSRProps ડાયરેક્ટિવ હૂકનો ઉપયોગ કરી શકો છો:
js
const myDirective = {
mounted(el, binding) {
// ક્લાયન્ટ-સાઇડ અમલીકરણ:
// DOM ને સીધું અપડેટ કરો
el.id = binding.value
},
getSSRProps(binding) {
// સર્વર-સાઇડ અમલીકરણ:
// રેન્ડર થનારા પ્રોપ્સ પરત કરો.
// getSSRProps ને માત્ર ડાયરેક્ટિવ બાઇન્ડિંગ મળે છે.
return {
id: binding.value
}
}
}ટેલિપોર્ટ્સ (Teleports)
SSR દરમિયાન ટેલિપોર્ટ્સને ખાસ હેન્ડલિંગની જરૂર હોય છે. જો રેન્ડર કરેલી એપ્લિકેશનમાં ટેલિપોર્ટ્સ હોય, તો ટેલિપોર્ટ કરેલી સામગ્રી રેન્ડર કરેલી સ્ટ્રિંગનો ભાગ રહેશે નહીં. એક સરળ ઉકેલ એ છે કે માઉન્ટ પર શરતી રીતે ટેલિપોર્ટ રેન્ડર કરવું.
જો તમારે ટેલિપોર્ટ કરેલી સામગ્રીને હાઇડ્રેટ કરવાની જરૂર હોય, તો તેઓ ssr કોન્ટેક્ષ ઓબ્જેક્ટની teleports પ્રોપર્ટી હેઠળ એક્સપોઝ કરવામાં આવે છે:
js
const ctx = {}
const html = await renderToString(app, ctx)
console.log(ctx.teleports) // { '#teleported': 'ટેનિપોર્ટ કરવામાં આવેલી સામગ્રી' }તમારે ટેલિપોર્ટ માર્કઅપને તમારા અંતિમ પેજ HTML માં સાચા સ્થાને ઇન્જેક્ટ કરવાની જરૂર છે જેમ કે તમારે મુખ્ય એપ માર્કઅપને ઇન્જેક્ટ કરવાની જરૂર છે.
TIP
ટેલિપોર્ટ્સ અને SSR નો સાથે ઉપયોગ કરતી વખતે લક્ષ્ય (targeting) body ટાળો - સામાન્ય રીતે, <body> માં અન્ય સર્વર-રેન્ડર્ડ સામગ્રી હશે જે ટેલિપોર્ટ્સ માટે હાઇડ્રેશન માટે યોગ્ય પ્રારંભિક સ્થાન નક્કી કરવાનું અશક્ય બનાવે છે.
તેના બદલે, સમર્પિત કન્ટેનર પસંદ કરો, દા.ત. <div id="teleported"></div> જેમાં માત્ર ટેલિપોર્ટ કરેલી સામગ્રી હોય.