5. [nuxt-02] örneği: sunucu ve istemci sayfaları
Bu projede şunu gösteriyoruz:
- istemci tarafından oluşturulan sayfanın, sunucudan alınan sayfadan görsel olarak farklı olabileceğini. Bu durumda, kullanıcı tarafından fark edilebilen hızlı bir sayfa değişimi meydana gelir ve bu da uygulamanın kullanıcı dostu olmamasına neden olur. Dolayısıyla bu, kaçınılması gereken bir seçenektir;
- istemci sayfasının, sunucu tarafından gönderilen sayfayla aynı sayfayı yeniden oluşturmasını sağlayan bir çözüm;
[nuxt-02] projesi, başlangıçta [nuxt-01] projesinin kopyalanmasıyla elde edilmiştir.

Projeye bir [store] klasörü ve iki yeni sayfa eklenmiştir. Buna daha sonra tekrar döneceğiz.
5.1. [index] sayfası
5.1.1. Sayfanın kodu
[index] sayfasının kodu şu şekilde olur:
<!-- ana sayfa -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj-->
<b-alert slot="right" show variant="warning"> Home - value= {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Home',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[home beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[home created]')
// sadece sunucu
if (process.server) {
this.value = 10
}
// istemci ve sunucu
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[home beforeMount]')
},
mounted() {
// sadece istemci
console.log('[home mounted]')
}
}
</script>
Açıklamalar
- 7. satır: [index] sayfası, [value] özelliğinin değerini (28. satır) görüntüleyecektir;
- 36-45. satırlar: Burada, [created] işlevinin hem sunucu tarafında hem de istemci tarafında yürütüldüğünü unutmamak gerekir. 40-42. satırlarda, sunucu [value] özelliğinin değerini 10 olarak ayarlayacaktır. İstemci ise bu değere dokunmaz. Sadece bu değerin istemci tarafından korunup korunmadığını öğrenmek istiyoruz. Korunmadığını göreceğiz;
5.1.2. Çalıştırma
[nuxt-02] projesini çalıştırmak için [/nuxt.config.js] dosyasını değiştiriyoruz:
...
// kaynak kod dizini
srcDir: 'nuxt-02',
// yönlendirici
router: {
// uygulamanın URL kök dizini
base: '/nuxt-02/'
},
// sunucu
server: {
// hizmet bağlantı noktası, varsayılan olarak 3000
port: 81,
// dinlenen ağ adresleri, varsayılan olarak localhost: 127.0.0.1
// 0.0.0.0 = makinedeki tüm ağ adresleri
host: 'localhost'
}
...
[1] projesini çalıştırıyoruz:

Bunun üzerine [index] sayfası, [2-3] olarak görüntülenir. Sayfa, bir süreliğine [10] değerini gösterir, ardından [0] değerini gösterir. Ne oldu?
1. adım
İlk olarak sunucu çalışır. [index] sayfasındaki kodu çalıştırır:
export default {
name: 'Home',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[home beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[home created]')
// sadece sunucu
if (process.server) {
this.value = 10
}
// istemci ve sunucu
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[home beforeMount]')
},
mounted() {
// sadece istemci
console.log('[home mounted]')
}
}
- 23. satır nedeniyle, 10. satırdaki [value] özelliği 10 değerini alır;
Bunu, tarayıcı tarafından alınan sayfanın kaynak koduna bakarak doğrulayabiliriz (tarayıcıdaki [code source] seçeneği):
<!doctype html>
<html data-n-head-ssr>
<head>
<title>Introduction à [nuxt.js]</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<base href="/nuxt-02/">
<link rel="preload" href="/nuxt-02/_nuxt/runtime.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/commons.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/app.js" as="script">
....
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<div id="__layout">
<div class="container">
<div class="card">
<div class="card-body">
<div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
<h4>[nuxt-02] : page serveur, page client</h4>
</div> <div>
<div class="row">
<div class="col-2">
<ul class="nav flex-column">
<li class="nav-item">
<a href="/nuxt-02/" target="_self" class="nav-link active nuxt-link-active">
Home
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page1" target="_self" class="nav-link">
Page 1
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page2" target="_self" class="nav-link">
Page 2
</a>
</li>
</ul>
</div> <div class="col-10">
<div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-warning">
Home - value= 10
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>window.__NUXT__ = ....;</script>
<script src="/nuxt-02/_nuxt/runtime.js" defer></script>
<script src="/nuxt-02/_nuxt/commons.app.js" defer></script>
<script src="/nuxt-02/_nuxt/vendors.app.js" defer></script>
<script src="/nuxt-02/_nuxt/app.js" defer></script>
</body>
</html>
- 46. satır: Alınan sayfada, [value]'in değeri 10'du;
2. adım
Sayfanın alınmasından sonra, 57-60. satırlardaki komut dosyalarının devreye girdiğini ve alınan sayfanın davranışını, hatta burada olduğu gibi görüntülenen bilgileri değiştirdiğini biliyoruz. Bu komut dosyaları, sunucudakiyle aynı olan [index] sayfasının kodunu da çalıştıran istemciyi oluşturur:
export default {
name: 'Home',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[home beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[home created]')
// sadece sunucu
if (process.server) {
this.value = 10
}
// istemci ve sunucu
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[home beforeMount]')
},
mounted() {
// sadece istemci
console.log('[home mounted]')
}
}
- Neler olduğunu anlamak için, [nuxt] istemcisinin 22-24. satırları çalıştırmayacağını (process.server=false) anlamak gerekir;
- klasik bir [vue] uygulamasında, 10. satırdaki [value] özelliği 0 olarak kalır. Bu nedenle, istemci alınan sayfaya geçtiğinde görüntülenen değer [0] olur;
[nuxt] sunucusu tarafından [value] özelliği için üretilen değer hiçbir işe yaramadı.
5.2. [page1] sayfası
5.2.1. [Vuex] mağazası
[nuxt-02] projesine [store] klasörünü ekledik:

Bu klasörün varlığı, [nuxt]'in otomatik olarak bir [Vuex] deposu uygulamasını sağlar. Bu depoyu uygulayan dosya [index.js]'tir. Burada, [index.js] dosyası şöyledir:
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state, inc) {
state.counter += inc
}
}
[nuxt], [index.js] dosyasının içeriğinden yola çıkarak [Vuex] depolama alanını oluşturur:
- 1-3. satırlar: deponun [state] durumunun tanımı. Bu durum bir işlev tarafından döndürülür. Burada durumun tek bir özelliği vardır: 2. satırdaki sayaç. Dışa aktarılan işlevin adı [state] olmalıdır;
- satır 5-9: depo durumu üzerinde gerçekleştirilebilecek işlemler. Bunlara [mutations] denir. Burada, [increment] mutasyonu, [counter] özelliğini [inc] miktarı kadar artırmaya olanak tanır. Dışa aktarılan nesnenin adı [mutations] olmalıdır;
[nuxt] tarafından uygulanan [store] Vuex, farklı yerlerde kullanılabilir. Görünümlerde, [this.$store] özelliğinde kullanılabilir.
5.2.2. Sayfa kodu
[index] sayfası gibi, [page1] sayfası da bir değer, yani Vuex depolama sayacının değerini gösterecektir:
<!-- sayfa 1 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj-->
<b-alert slot="right" show variant="primary"> Page 1 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page1',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[home beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[home created]')
// sadece sunucu
if (process.server) {
this.$store.commit('increment', 25)
}
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[home beforeMount]')
},
mounted() {
// sadece istemci
console.log('[home mounted]')
}
}
</script>
Açıklamalar
- 38-40. satırlar: sunucu sayacı 25 artıracaktır;
- 42. satır: Hem sunucu hem de istemci sayaç değerini görüntüleyecektir;
- 7. satır: Sayaç değeri görüntülenir;
Bu kodu okurken iki şeyi anlamak gerekir:
- sunucu ve istemci için yürütülen kod aynıdır;
- [this] nesnesi ise aynı değildir: sunucu tarafında [this] sürümü, istemci tarafında ise [client] sürümü bulunmaktadır;
Sunucudaki [this.$store] nesnesinin, istemcideki [this.$store] nesnesiyle aynı olup olmadığını öğrenmeye çalışıyoruz. (Uygulamanın başlatılması sırasında) önce sunucu çalıştığı için, bu şu soruyu sormakla eşdeğerdir: Sunucu tarafından başlatılan [store], istemciye aktarılıyor mu?
5.2.3. Çalıştırma
[nuxt-02] projesini çalıştırıyoruz ve sunucuyu tetiklemek için elle [localhost:81/nuxt-02/page1] yazıyoruz. [index] sayfası için başlangıçta olduğu gibi:
- sunucu [page1.vue] sayfasını çalıştırır;
- oluşturulan sayfayı tarayıcıya gönderir. Sayfa görüntülenir;
- gönderilen sayfada yer alan istemci komut dosyaları devreye girer ve [page1.vue] sayfasını yeniden çalıştırır;
- görüntülenen sayfa bu şekilde değiştirilir;
Nihai sonuç şöyledir:

Bu sefer, görüntülenen değer sunucu tarafından belirlenen değerle aynıdır ve görsel olarak, sunucu tarafından görüntülenen değerin istemci tarafından değiştirilmesi nedeniyle sayfanın "sarsıldığı" görülmez. Peki bu sefer ne oldu?
Sunucu, aşağıdaki [page1] sayfasını çalıştırdı:
...
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page1',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page1 beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[page1 created]')
// sadece sunucu
if (process.server) {
this.$store.commit('increment', 25)
}
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page1 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page1 mounted]')
}
}
</script>
- 30-32. satırlar hatasız bir şekilde çalıştırıldı. Bu, sunucu tarafında da [this.$store]'in [Vuex] depolama alanını işaret ettiği anlamına gelir. 31. satır, depolama alanının sayacını 25'e yükseltti;
- bunun ardından sayfa müşteriye gönderildi;
İstemci tarafından alınan sayfaya bakıldığında şu öğeler görülür:
<!doctype html>
<html data-n-head-ssr>
<head>
<title>Introduction à [nuxt.js]</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<base href="/nuxt-02/">
<link rel="preload" href="/nuxt-02/_nuxt/runtime.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/commons.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/app.js" as="script">
...
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<div id="__layout">
<div class="container">
<div class="card">
<div class="card-body">
<div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
<h4>[nuxt-02] : page serveur, page client</h4>
</div>
<div>
<div class="row">
<div class="col-2">
<ul class="nav flex-column">
<li class="nav-item">
<a href="/nuxt-02/" target="_self" class="nav-link">
Home
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page1" target="_self" class="nav-link active nuxt-link-active">
Page 1
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page2" target="_self" class="nav-link">
Page 2
</a>
</li>
</ul>
</div> <div class="col-10">
<div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-primary">
Page 1 - value = 25
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
window.__NUXT__ = (function (a, b, c) {
return {
layout: "default", data: [{}], error: null, state: { counter: 25 }, serverRendered: true,
logs: [
{ date: new Date(1574085336802), args: ["[home beforeCreate]"], type: a, level: b, tag: c },
{ date: new Date(1574085336839), args: ["[home created]"], type: a, level: b, tag: c },
{ date: new Date(1574085336869), args: ["value=", "25"], type: a, level: b, tag: c }
]
}
}("log", 2, ""));</script>
<script src="/nuxt-02/_nuxt/runtime.js" defer></script>
<script src="/nuxt-02/_nuxt/commons.app.js" defer></script>
<script src="/nuxt-02/_nuxt/vendors.app.js" defer></script>
<script src="/nuxt-02/_nuxt/app.js" defer></script>
</body>
</html>
- 47. satır: sunucu tarafından gönderilen değer;
- 60. satır: [Vuex] depolama alanının durumunun sayfaya eklendiği görülür. Bu, sayfayı aldıktan sonra çalışacak olan istemcinin, sayacın başlangıç değeri 25 olarak ayarlanmış yeni bir [Vuex] depolama alanı oluşturmasına olanak tanıyacaktır;
Sunucudan alınan sayfanın alınması ve görüntülenmesinden sonra, istemci devreye girer ve sırayla [page1] sayfasını çalıştırır:
...
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page1',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page1 beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[page1 created]')
// sadece sunucu
if (process.server) {
this.$store.commit('increment', 25)
}
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page1 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page1 mounted]')
}
}
</script>
- 34. satır: 18. satırdaki [value] özelliği de sırayla sayaçtan 25 değerini alır;
Dolayısıyla, [nuxt] deposu, sayfa sunucuda arandığında, sayfanın ilk yüklenmesi sırasında sunucunun istemciye bilgi aktarmasına olanak tanır. Bu sayfa alındıktan sonra sunucuya artık yük binmez ve uygulama, SAP modunda klasik bir [vue] uygulaması gibi çalışır.
5.3. [page2] sayfası
[page2] sayfasında, sunucunun sayfaya hesaplanmış bilgileri eklemesinin başka bir yolunu gösteriyoruz:
- sunucunun sayfaya hesaplanmış bilgileri eklemesi;
- istemcinin bu bilgileri değiştirmemesi;
5.3.1. Sayfanın kodu
[page2] sayfasının kodu şu şekilde değişir:
<!-- sayfa 2 -->
<template>
<Layout :left="true" :right="true">
<!-- navigasyon -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 2 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page2',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
asyncData(context) {
// bu kodu kim çalıştırıyor?
console.log('asyncData, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleme süresiyle simüle ediyoruz
setTimeout(() => {
// bu sonuç, [data]'in özelliklerine eklenecektir
resolve({ value: 87 })
// günlüğü
console.log('asynData terminée')
}, 1000)
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page2 beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[page2 created]')
},
beforeMount() {
// sadece istemci
console.log('[page2 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page2 mounted]')
}
}
</script>
- 7. satır: Sayfa, [value] adlı bir özelliğin değerini görüntüler;
- [value] özelliği, [data] işlevi tarafından döndürülen bir nesnenin öğesi olarak mevcut değildir. Burada bu işlev mevcut değildir. [value] özelliği, 36. satır tarafından dinamik olarak oluşturulur;
- 25. satır: [asyncData] işlevi, bir [nuxt] işlevidir. Adından da anlaşılacağı gibi, bu normalde asenkron bir işlevdir. Genellikle dış verileri almakla görevlidir. [nuxt], [asyncData] işlevi asenkron verilerini döndürmeden önce sayfanın istemci tarayıcısına gönderilmemesini sağlar;
- [asyncData] işlevi, parametre olarak [nuxt] bağlamını alır. Bu nesne oldukça kapsamlıdır ve [nuxt] uygulaması hakkında birçok bilgiye erişim sağlar. Bunu ilerleyen bölümlerde göreceğiz;
- 31. satır: [asyncData] işlevini bir [Promise] ile uyguluyoruz (bkz. |Introduction au langage ECMASCRIPT 6 par l’exemple| belgesi). Bu sınıfın oluşturucusu, parametre olarak aşağıdaki işlevi yerine getiren bir asenkron işlevi kabul eder:
- [resolve] işleviyle veri döndürerek başarıyı bildirir. Bu işlev tarafından döndürülen nesne, sayfanın [data] özelliklerine otomatik olarak eklenir;
- [reject] işleviyle bir hata döndürerek başarısızlığı bildirir;
- 34. satır: [setTimeout] işleviyle asenkron bir işlev simüle edilir. Bu işlev, [Promise] işlevinin başarılı olduğunu bildiren [resolve] işlevi sayesinde bir saniye sonra (satır 31) [{ value: 87 }] nesnesini (satır 36) döndürür. Asenkron işlev tarafından döndürülen nesne, sayfanın [data] özelliklerine otomatik olarak eklenir. Dolayısıyla 7. satırda görüntülenen de bu özelliktir;
- 27. satır: [asyncData] işlevinin sunucu tarafından yürütüldüğünü, ancak istemci tarafından yürütülmediğini göreceğiz;
- 29. satır: [value] özelliğinin başlatılması sunucu tarafından yapılır;
Not: [this] nesnesi, [asyncData] işlevinde tanınmamaktadır; çünkü [vue] bileşenini kapsayan nesne henüz oluşturulmamıştır;
5.3.2. Çalıştırma
[nuxt-02] projesini çalıştırıyoruz ve sunucuyu çağırmak için [localhost:81/nuxt-02/page2] adresini manuel olarak giriyoruz. [index] sayfası için başlangıçta olduğu gibi:
- sunucu [page2.vue] sayfasını çalıştırır;
- oluşturulan sayfayı tarayıcıya gönderir. Sayfa görüntülenir;
- gönderilen sayfada yer alan istemci komut dosyaları devreye girer ve [page2.vue] sayfasını yeniden çalıştırır;
- görüntülenen sayfa bu şekilde değiştirilir;
Nihai sonuç şöyledir:

Bu sefer, görüntülenen değer sunucu tarafından belirlenen değerle aynıdır ve görsel olarak, sunucu tarafından görüntülenen değerin istemci tarafından değiştirilmesi nedeniyle sayfanın "sarsıldığı" görülmez. Peki bu sefer ne oldu?
Sunucu, aşağıdaki [page2] sayfasını çalıştırdı:
<!-- sayfa 2 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 2 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page2',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
asyncData(context) {
// bu kodu kim çalıştırıyor?
console.log('asyncData, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// bu sonuç, [data]'in özelliklerine eklenecektir
resolve({ value: 87 })
// günlüğü
console.log('asynData terminée')
}, 1000)
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page2 beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[page2 created]')
},
beforeMount() {
// sadece istemci
console.log('[page2 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page2 mounted]')
}
}
</script>
- satırda görüntülenen değeri belirleyen 36. satırdır. Dolayısıyla, istemci tarayıcısı bunu almıştır. Tam olarak şu sayfayı almıştır:
<!doctype html>
<html data-n-head-ssr>
<head>
<title>Introduction à [nuxt.js]</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<base href="/nuxt-02/">
<link rel="preload" href="/nuxt-02/_nuxt/runtime.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/commons.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/app.js" as="script">
...
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<div id="__layout">
<div class="container">
<div class="card">
<div class="card-body">
<div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
<h4>[nuxt-02] : page serveur, page client</h4>
</div>
<div>
<div class="row">
<div class="col-2">
<ul class="nav flex-column">
<li class="nav-item">
<a href="/nuxt-02/" target="_self" class="nav-link">
Home
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page1" target="_self" class="nav-link">
Page 1
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page2" target="_self" class="nav-link active nuxt-link-active">
Page 2
</a>
</li>
</ul>
</div>
<div class="col-10">
<div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-secondary">
Page 2 - value = 87
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
window.__NUXT__ = (function (a, b, c) {
return {
layout: "default", data: [{ value: 87 }], error: null, state: { counter: 0 }, serverRendered: true,
logs: [
{ date: new Date(1574096608555), args: ["asyncData, client=", "false", "serveur=", "true"], type: a, level: b, tag: c },
{ date: new Date(1574096608575), args: ["[page2 beforeCreate]"], type: a, level: b, tag: c },
{ date: new Date(1574096608599), args: ["[page2 created]"], type: a, level: b, tag: c }
]
}
}("log", 2, ""));</script>
<script src="/nuxt-02/_nuxt/runtime.js" defer></script>
<script src="/nuxt-02/_nuxt/commons.app.js" defer></script>
<script src="/nuxt-02/_nuxt/vendors.app.js" defer></script>
<script src="/nuxt-02/_nuxt/app.js" defer></script>
</body>
</html>
- 48. satır: Alınan sayfadaki değerin 87 olduğu görülüyor;
- 61. satır: Sunucunun yanıtında iki nesne görülüyor: [data] ve [state]:
- [state], [Vuex] mağazasının durumudur. Bu mağaza, [nuxt-02] uygulamasının [store] klasöründeki içerikten oluşturulmuştur;
- [data], [asyncData] işlevi aracılığıyla sunucu tarafından oluşturulan özellikleri içerir. Sunucu tarafından oluşturulan [value : 87] özelliğini görüyoruz. İstemci komut dosyaları bu özelliği [page2] sayfasının özelliklerine entegre edecektir;
[page2] sayfasının koduna geri dönelim:
<!-- sayfa 2 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 2 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page2',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
asyncData(context) {
// bu kodu kim çalıştırıyor?
console.log('asyncData, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// bu sonuç, [data]'in özelliklerine eklenecektir
resolve({ value: 87 })
// günlüğü
console.log('asynData terminée')
}, 1000)
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page2 beforeCreate]')
},
created() {
// istemci ve sunucu
console.log('[page2 created]')
},
beforeMount() {
// sadece istemci
console.log('[page2 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page2 mounted]')
}
}
</script>
- 7. satırda [value] özelliği kullanılmaktadır. Oysa sayfada [value] adlı herhangi bir özellik tanımlanmamıştır. Bununla birlikte, istemci tarafındaki komut dosyaları, sunucudan alınan [data: [{ value: 87 }]] nesnesi sayesinde bu özelliği otomatik olarak oluşturmuştur;
Ayrıca günlük kayıtları, [asyncData] işlevinin istemci tarafından çalıştırılmadığını göstermektedir:

[asyncData] işlevi, [1] sunucusu tarafından çalıştırılmış, ancak [2] istemcisi tarafından çalıştırılmamıştır. Ayrıca, [asyncData] işlevinin tamamlanmasından önce sunucu tarafından yaşam döngüsü işlevlerinin yürütülmediği de görülebilir. Bunu doğrulamak için [asyncData] işlevi içindeki bekleme süresini uzatabilirsiniz.
5.4. [page3] sayfası
Uygulamamıza yeni bir [page3] sayfası ekliyoruz:

5.4.1. [navigation] bileşeni
[vavigation] bileşeni, yeni sayfaya geçiş yapılabilmesi için değiştirildi:
<template>
<!-- üç seçenekli Bootstrap menüsü -->
<b-nav vertical>
<b-nav-item to="/" exact exact-active-class="active">
Home
</b-nav-item>
<b-nav-item to="/page1" exact exact-active-class="active">
Page 1
</b-nav-item>
<b-nav-item to="/page2" exact exact-active-class="active">
Page 2
</b-nav-item>
<b-nav-item to="/page3" exact exact-active-class="active">
Page 3
</b-nav-item>
</b-nav>
</template>
5.4.2. [page3] kodunu
[page3] sayfasının kodu şöyledir:
<!-- sayfa 3 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 3 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page3',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
fetch(context) {
// bu kodu kim çalıştırıyor?
console.log('fetch, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz (promise) döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// başarılı
resolve()
}, 1000)
}).then(() => {
// depolama alanı değiştiriliyor
context.store.commit('increment', 28)
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page3 beforeCreate]')
},
created() {
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('[page3 created], value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page3 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page3 mounted]')
}
}
</script>
- 30. satır: [fetch] işlevi, [asyncData] işlevine benzer bir davranış sergiler:
- yaşam döngüsü işlevlerinden önce yürütülür;
- bu işlevde [this] nesnesi tanınmaz;
- çalışması asenkron;
- asenkron işlev sonucunu döndürene kadar yaşam döngüsü başlamaz;
- sonuç, burada [Promise]'in 43. satırındaki [then] yöntemi tarafından döndürülür;
- [fetch] işlevi, [context] parametresini alır. Bu parametre, o anki [nuxt] bağlamını temsil eder;
- 30. satır: [context] nesnesinin sayısız özelliği arasında, uygulamanın [Vuex] mağazasını temsil eden [store] özelliği bulunmaktadır;
- 41. satır: Yapay olarak, bir saniye sonra [Promise]'in başarılı olduğu bildirilir (bkz. |Introduction au langage ECMASCRIPT 6 par l’exemple| belgesi);
- 45. satır: Ardından [then] yöntemi yürütülür. Burada [store]'in sayacı artırılır;
5.4.3. Çalıştırma
[nuxt-02] projesini çalıştırıyoruz ve sunucuya istek gönderilmesi için [localhost:81/nuxt-02/page3] adresini manuel olarak giriyoruz. [index] sayfası için başlangıçta olduğu gibi:
- sunucu [page3.vue] sayfasını çalıştırır;
- oluşturulan sayfayı tarayıcıya gönderir. Sayfa görüntülenir;
- gönderilen sayfada yer alan istemci komut dosyaları devreye girer ve [page3.vue] sayfasını yeniden çalıştırır;
- görüntülenen sayfa bu şekilde değiştirilir;
Nihai sonuç şöyledir:

Görüntülenen değer, sunucu tarafından belirlenen değerle aynıdır ve görsel olarak, sunucu tarafından görüntülenen değerin istemci tarafından değiştirilmesi nedeniyle sayfanın "sarsıldığı" görülmez. Peki bu sefer ne oldu?
Sunucu, aşağıdaki [page3] sayfasını çalıştırdı:
<!-- sayfa 3 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 3 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page3',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
fetch(context) {
// bu kodu kim çalıştırıyor?
console.log('fetch, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz (promise) döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// başarılı
resolve()
}, 1000)
}).then(() => {
// depolama alanı değiştirilir
context.store.commit('increment', 28)
// günlük
console.log('fetch commit terminé')
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page3 beforeCreate]')
},
created() {
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('[page3 created], value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page3 beforeMount]')
},
mounted() {
// sadece müşteri
console.log('[page3 mounted]')
}
}
</script>
- 45. satır: Asenkron [fetch] işlevi, yukarıdaki işlevler arasında ilk olarak çalıştırılan işlevdir. Bu işlev, parametre olarak [context] adlı bir nesne alır; bu nesne, o anki [nuxt] bağlamını temsil eder. Bu nesnenin çok sayıdaki özelliğinden biri olan [context.store] özelliği, [Vuex] depolama alanını temsil eder;
- 45. satır: [fetch] asenkron fonksiyonunda, sunucu deponun sayacını 28 olarak ayarlar;
- 56. satır: [created] işlevi yürütüldüğünde, [nuxt], asenkron [fetch] işlevinin işini tamamladığından emin olur;
- satır 58: perde sayacının değeri, 27. satırdaki [value] özelliğine atanır;
- 7. satır: [value] değeri, yani depolama sayacının değeri görüntülenir;
İstemci tarayıcısı şu sayfayı alır:
<!doctype html>
<html data-n-head-ssr>
<head>
<title>Introduction à [nuxt.js]</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<base href="/nuxt-02/">
<link rel="preload" href="/nuxt-02/_nuxt/runtime.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/commons.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/nuxt-02/_nuxt/app.js" as="script">
...
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<div id="__layout">
<div class="container">
<div class="card">
<div class="card-body">
<div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
<h4>[nuxt-02] : page serveur, page client</h4>
</div>
<div>
<div class="row">
<div class="col-2">
<ul class="nav flex-column">
<li class="nav-item">
<a href="/nuxt-02/" target="_self" class="nav-link">
Home
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page1" target="_self" class="nav-link">
Page 1
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page2" target="_self" class="nav-link">
Page 2
</a>
</li>
<li class="nav-item">
<a href="/nuxt-02/page3" target="_self" class="nav-link active nuxt-link-active">
Page 3
</a>
</li>
</ul>
</div> <div class="col-10">
<div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-secondary">
Page 3 - value = 28
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
window.__NUXT__ = (function (a, b, c) {
return {
layout: "default", data: [{}], error: null, state: { counter: 28 }, serverRendered: true,
logs: [
{ date: new Date(1574169916025), args: ["fetch, client=", "false", "serveur=", "true"], type: a, level: b, tag: c },
{ date: new Date(1574169917038), args: ["fetch commit terminé"], type: a, level: b, tag: c },
{ date: new Date(1574169917137), args: ["[page3 beforeCreate]"], type: a, level: b, tag: c },
{ date: new Date(1574169917167), args: ["[page3 created], value=", "28"], type: a, level: b, tag: c }
]
}
}("log", 2, ""));</script>
<script src="/nuxt-02/_nuxt/runtime.js" defer></script>
<script src="/nuxt-02/_nuxt/commons.app.js" defer></script>
<script src="/nuxt-02/_nuxt/vendors.app.js" defer></script>
<script src="/nuxt-02/_nuxt/app.js" defer></script>
</body>
</html>
- 52. satır: Alınan sayfadaki değerin 28 olduğu görülüyor;
- 65. satır: Sunucunun yanıtında, sunucunun [Vuex] depolama alanının [state] durumunu istemciye gönderdiği görülüyor. Bu bilgi sayesinde, istemci komut dosyaları bir [Vuex] depolama alanını yeniden oluşturabilecek;
İstemci komut dosyaları da sırayla [page3] sayfasının kodunu çalıştıracaktır:
<!-- sayfa 3 -->
<template>
<Layout :left="true" :right="true">
<!-- navigasyon -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 3 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page3',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
fetch(context) {
// bu kodu kim çalıştırıyor?
console.log('fetch, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz (promise) döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// başarılı
resolve()
}, 1000)
}).then(() => {
// depolama alanı değiştirilir
context.store.commit('increment', 28)
// günlük
console.log('fetch commit terminé')
})
}
},
// yaşam döngüsü
beforeCreate() {
// istemci ve sunucu
console.log('[page3 beforeCreate]')
},
created() {
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('[page3 created], value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page3 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page3 mounted]')
}
}
</script>
- 58. satır: İstemci tarafından yürütülen [created] işlevi, sayaç değerini 27. satırdaki [value] özelliğine atar;
- 7. satırda bu değer görüntülenir. Bu değer, sunucu tarafından gönderilen değerle aynı olduğu için, bir değişiklik nedeniyle sayfanın "sarsılma" etkisi görülmez;
Ayrıca günlükler, [fetch] işlevinin istemci tarafından çalıştırılmadığını göstermektedir:

[fetch] işlevi, [1] sunucusu tarafından yürütülmüştür, ancak [2] istemcisi tarafından yürütülmemiştir. Ayrıca, [fetch] ve [3] işlevleri tamamlanmadan önce yaşam döngüsü işlevlerinin sunucu tarafından yürütülmediğine dikkat edilebilir. Bunu doğrulamak için [fetch] işlevi içindeki bekleme süresini uzatabilirsiniz.
[page1] ve [page3] sayfaları, sunucudan istemciye bilgi aktarmak için [Vuex] depolama alanını kullanan iki yöntem göstermiştir. Bu yöntemlerin eşdeğer olup olmadığı sorgulanabilir. Bunu doğrulamak için [page4] sayfasını oluşturuyoruz.
5.5. [page4] sayfası
Uygulamamıza yeni bir [page4] sayfası ekliyoruz:

5.5.1. [navigation] bileşeni
[navigation] bileşeni, yeni sayfaya geçiş yapılabilmesi için değiştirildi:
<template>
<!-- Beş seçenekli Bootstrap menüsü -->
<b-nav vertical>
<b-nav-item to="/" exact exact-active-class="active">
Home
</b-nav-item>
<b-nav-item to="/page1" exact exact-active-class="active">
Page 1
</b-nav-item>
<b-nav-item to="/page2" exact exact-active-class="active">
Page 2
</b-nav-item>
<b-nav-item to="/page3" exact exact-active-class="active">
Page 3
</b-nav-item>
<b-nav-item to="/page4" exact exact-active-class="active">
Page 4
</b-nav-item>
</b-nav>
</template>
5.5.2. [page4] kodunu
[page4] sayfasının kodu şöyledir:
<!-- sayfa4 -->
<template>
<Layout :left="true" :right="true">
<!-- gezinme -->
<Navigation slot="left" />
<!-- mesaj -->
<b-alert slot="right" show variant="secondary"> Page 4 - value = {{ value }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Page4',
// kullanılan bileşenler
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// yaşam döngüsü
async beforeCreate() {
// istemci ve sunucu
console.log('[page4 beforeCreate]')
// sadece sunucu için
if (process.server) {
// asenkron işlevi çalıştırılır
const valeur = await new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// 10 saniyelik bir bekleme süresiyle simüle ediliyor
setTimeout(() => {
// başarılı - sayaç değeri döndürülür
resolve(52)
}, 10000)
})
// depolama alanını değiştiriyoruz
this.$store.commit('increment', valeur)
// günlük
console.log('[page4 beforeCreate], fonction asynchrone terminée, compteur=', this.$store.state.counter)
}
},
created() {
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('[page4 created], value=', this.value)
},
beforeMount() {
// sadece istemci
console.log('[page4 beforeMount]')
},
mounted() {
// sadece istemci
console.log('[page4 mounted]')
}
}
</script>
- 30. satır: Daha önce [fetch] işlevinde yapılan işlem artık [beforeCreate] yönteminde gerçekleştirilmektedir. Asenkron işlevin tamamlanmasını beklemek için async (30. satır) / await (36. satır) çifti kullanılmaktadır;
- satır 36: 10 saniye sonra (satır 42) satır 41'de asenkron fonksiyonun sonucu alınır;
- satır 50-54: hem sunucu tarafında hem de istemci tarafında yürütülen [created] yönteminde, sayaç sayfanın [value] özelliğine atanır;
5.5.3. Çalıştırma
[nuxt-02] projesini çalıştırıyoruz ve sunucuya istek gönderilmesi için [localhost:81/nuxt-02/page4] adresini elle giriyoruz. [index] sayfası için başlangıçta olduğu gibi:
- sunucu [page4.vue] sayfasını çalıştırır;
- oluşturulan sayfayı tarayıcıya gönderir. Sayfa görüntülenir;
- gönderilen sayfada yer alan istemci komut dosyaları devreye girer ve [page4.vue] sayfasını yeniden çalıştırır;
- görüntülenen sayfa bu şekilde değiştirilir;
Nihai sonuç şöyledir:

Beklenilenin aksine, [2]'te görüntülenen değer 52 değildir. Ne oldu?
Günlük kayıtları şu şekildedir:

[1]'te asenkron işlemin sonuna ait günlüğün görüntülenmediği görülebilir. Sayaç değerini görüntüleyen [created] işlevi, 0 değerini gösteriyor. Tüm bunlar, [nuxt]'in asenkron işlemin bitmesini beklemediğini düşündürüyor.
Uygulamanın başlatılmasında kullanılan VSCode terminaline geri dönersek, [3-4] günlüklerini görürüz. Asenkron işlevin sunucu tarafında başarıyla yürütüldüğü anlaşılmaktadır.
Sonuç olarak, [beforeCreate] işlevi sunucu tarafında tamamen yürütülmüştür, ancak [nuxt], [fetch] işlevinin tamamlanmasını beklerken, kendi yürütülmesinin bitmesini beklemeden sayfayı istemci tarayıcısına göndermiştir. Dolayısıyla, sunucunun bir [Vuex] deposunu başlatmasını istiyorsak bu yöntemi kullanmamız gerekir.
5.6. [vue] uygulamasında gezinme
Her bir [index, page1, page2, page3, page4] sayfasının sunucu tarafından ilk kez yüklendiğinde neler olduğunu gösterdik. Pratikte durum böyle değildir: normal çalışma koşullarında, sunucuda yalnızca [index] sayfası aranır. Bu durumda üç sayfayı inceleyelim:
[index] sayfası

Bu sonucu daha önce “bağlantı” başlığı altında açıklamıştık.
Şimdi [Page 1] bağlantısına tıklayalım:

Görüntülenen değer 0'dır. Sayfanın URL adresi elle girilerek sunucuya ilk kez istendiğinde bu değer 25 idi. Bunun açıklaması basit. Yürütülen kod şöyledir:
created() {
// istemci ve sunucu
console.log('[page1 created]')
// sadece sunucu
if (process.server) {
this.$store.commit('increment', 25)
}
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('value=', this.value)
},
Sayaç değerini 25'e ayarlayan 6. satırdı. Sayfa sunucudan talep edilmediğinden, 5-7. satırlar çalıştırılmadı ve [Vuex] depolama alanındaki sayaç değeri 0 olarak kaldı.
Şimdi [Page 2] bağlantısına tıklayalım:

Bu sefer hiçbir değer görüntülenmiyor ve ayrıca konsol günlüklerinde bir uyarı görünüyor:

- [1]'te, [asyncData] işlevinin istemci tarafından yürütüldüğünü görüyoruz. Her zaman böyledir:
- sayfa sunucudan istenirse işlev sunucu tarafından yürütülür. Bu durumda işlev istemci tarafından yürütülmez;
- ancak sayfa, istemcinin geçerli yolunun hedefi olduğunda her seferinde;
- [2]'te: [nuxt] bir uyarı verir çünkü sayfanın şablonunda {{ value }} adlı reaktif bir ifade varken, sayfanın [value] özelliği yoktur;
İstemci tarafından yürütülen kodu hatırlayalım:
asyncData() {
// bu kodu kim çalıştırıyor?
console.log('asyncData, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz döndürülür
return new Promise(function(resolve, reject) {
// normalde burada asenkron bir işlev olurdu - ama burada yok
// bu sonuç, [data]'in özelliklerine eklenecek
resolve({ value: 87 })
})
}
},
- 3. satırda, [asyncData] işlevinin yaşam döngüsü işlevlerinden önce istemci tarafından yürütüldüğü görüldü;
- 5. satır, [value] özelliğini oluşturan kodun geri kalanının yürütülmesini engelledi, çünkü bu kod istemci tarafından yürütülür;
Şimdi [page3] sayfasına geçelim:

- [2]'te, sayfa sunucu tarafından sağlandığında 28 değeri vardı. Burada durum böyle değil;
- [4]'te, [fetch] işlevinin istemci tarafında yürütüldüğünü görüyoruz;
İstemci tarafından yürütülen kodu inceleyelim:
...
fetch(context) {
// Bu kodu kim çalıştırıyor?
console.log('fetch, client=', process.client, 'serveur=', process.server)
// sadece sunucu için
if (process.server) {
// bir söz döndürülür
return new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// bir saniye bekleyerek simüle ediyoruz
setTimeout(() => {
// başarılı
resolve()
}, 1000)
}).then(() => {
// depolama alanı değiştirilir
context.store.commit('increment', 28)
// günlük
console.log('fetch commit terminé')
})
}
},
...
- istemci, 2. satırdaki [fetch] yöntemini çalıştırır;
- 6-21. satırlar, [process.server] koşulu yanlış olduğu için yürütülmez. Dolayısıyla, sayacı 28'e ayarlayan 17. satır yürütülmez. Sayı sıfır olarak kalır. Bu nedenle istemci 28 yerine 0'ı görüntüler;
Şimdi [page4] sayfasına geçelim. Şu sonuç elde edilir:

- [2]'te, sayaç değeri;
- [3]'te, istemcinin günlükleri;
İstemci tarafından yürütülen kod şöyledir:
...
data() {
return {
value: 0
}
},
// yaşam döngüsü
async beforeCreate() {
// istemci ve sunucu
console.log('[page4 beforeCreate]')
// sadece sunucu için
if (process.server) {
// asenkron işlevi çalıştırılıyor
const valeur = await new Promise(function(resolve, reject) {
// burada normalde asenkron bir işlev bulunur
// 10 saniyelik bir bekleme süresiyle simüle ediliyor
setTimeout(() => {
// başarılı - sayaç değeri döndürülür
resolve(52)
}, 10000)
})
// depolama alanını değiştiriyoruz
this.$store.commit('increment', valeur)
// günlük
console.log('[page4 beforeCreate], fonction asynchrone terminée, compteur=', this.$store.state.counter)
}
},
created() {
// istemci ve sunucu
this.value = this.$store.state.counter
console.log('[page4 created], value=', this.value)
},
...
- 12-26. satırlar istemci tarafından yürütülmez, çünkü 12. satırdaki [process.server] koşulu yanlış çıkmaktadır. Dolayısıyla [Vuex] depolama alanındaki sayaç değeri 0'dır (depolama alanındaki başlangıç değeri) ve sayfa bu değeri görüntüler;
- ve 26. satırlardaki [if] koşulunu yorum satırına aldığımızda ne olacağı merak edilebilir. İşte cevabı:
- bu sefer istemci 14-25. satırları yürütür, ancak [nuxt], asenkron fonksiyonun bitmesini beklemez (sunucuda olduğu gibi) ve bu nedenle sayacı 0 olarak bırakır;
- 10 saniye sonra asenkron işlev sona erer ve 23. satırda sayaç 52'ye ayarlanır;
- [page4] sayfasına tekrar gidildiğinde, 52 değeri görüntülenir;
5.7. Résumé
Yaptığımız çeşitli denemelerden şu noktalar öne çıkmaktadır:
- [index] sayfası harici veriler içermesi gerekiyorsa, bu veriler [asyncData] işlevi kullanılarak sunucu tarafından aranabilir;
- sunucu, [index] sayfasının yüklenmesi sırasında bir [Vuex] depolama alanını harici verilerle başlatmak zorundaysa, bunu [fetch] işlevi içinde yapacaktır;
- sunucu tarafından oluşturulan sayfa ile istemci tarafından oluşturulan sayfa, istemcinin sayfası sunucu tarafından gönderilen ve başlangıçta görüntülenen sayfanın yerini görsel olarak alması nedeniyle ortaya çıkan “sarsılma” etkisini önlemek için aynı olmalıdır;
Yeni bir örnek üzerinden [nuxt]'in diğer yönlerini inceleyeceğiz.