Pre-rendering
Varsayılan olarak, Next.js her sayfayı önceden işler . Bu, Next.js’nin istemci tarafı JavaScript tarafından yapılması yerine her sayfa için önceden HTML oluşturduğu anlamına gelir. Ön işleme, daha iyi performans ve SEO ile sonuçlanabilir.
Oluşturulan her HTML, o sayfa için gerekli olan minimum JavaScript koduyla ilişkilendirilir. Bir sayfa tarayıcı tarafından yüklendiğinde, JavaScript kodu çalışır ve sayfayı tamamen etkileşimli hale getirir. (Bu işleme hidrasyon denir .)
Two forms of Pre-rendering
Next.js’nin iki ön işleme biçimi vardır: Statik Oluşturma ve Sunucu Tarafı İşleme . Fark, bir sayfa için HTML oluşturduğundadır.
- Statik Oluşturma Static Generation (Önerilen) : HTML, derleme zamanında oluşturulur ve her istekte yeniden kullanılır.
- Sunucu Tarafı Oluşturma — Server-side Rendering : HTML, her istekte oluşturulur .
Next.js , her sayfa için kullanmak istediğiniz ön işleme formunu seçmenize izin verir. Çoğu sayfa için Statik Oluşturma’yı ve diğerleri için Sunucu Tarafı İşleme’yi kullanarak bir “karma” Next.js uygulaması oluşturabilirsiniz.
Performans nedenleriyle Sunucu Tarafı Oluşturma yerine Statik Üretimi kullanmanızı öneririz . Statik olarak oluşturulmuş sayfalar, performansı artırmak için ekstra yapılandırma olmadan CDN tarafından önbelleğe alınabilir. Ancak bazı durumlarda Sunucu Tarafı Oluşturma tek seçenek olabilir. [Content Delivery Network (CDN) İçerik dağıtım ağı anlamına gelir]
Statik Üretim veya Sunucu Client-side Rendering (Tarafı İşleme ile birlikte İstemci Tarafı İşleme’yi) de kullanabilirsiniz . Bu, bir sayfanın bazı bölümlerinin tamamen istemci tarafı JavaScript tarafından oluşturulabileceği anlamına gelir.
Static Generation (Önerilen)
Bir sayfa Statik Üretim kullanıyorsa , sayfa HTML’si build time’da oluşturulur . Bu, next build
,komutu çalıştırdığında sayfa HTML’sinin oluşturulduğu anlamına gelir . Bu HTML daha sonra her istekte yeniden kullanılacaktır. Bir CDN tarafından önbelleğe alınabilir
Static Generation with data
Bazı sayfalar, ön işleme için harici verilerin alınmasını gerektirir. İki senaryo vardır ve biri veya her ikisi de geçerli olabilir. Her durumda, Next.js’nin sağladığı şu işlevleri kullanabilirsiniz
- Sayfa içeriğiniz (content) harici verilere bağlıdır:
getStaticProps
. - Sayfa içeriğiniz (content) path ile verilere bağlıdır getStaticPaths ve getStaticProps
Senaryo 1 : Sayfa içeriğiniz (content) harici verilere bağlıdır: getStaticProps
.
Elimizde bir blog içeriği yönetme uygulaması olduğunu düşünelim. Ve ekteki gibi bir comp olsun .
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
Pre-render aşamasında veriyi çekmek için NextJS async olan ve export edilmesi gereken bir fonksiyon kullanmamızı bekler.
// This function gets called at build time
export async function getStaticProps() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}export default Blog
Senaryo 2 Sayfa içeriğiniz (content) path ile verilere bağlıdır.
Next.js, dinamik rotalara sahip sayfalar oluşturmanıza olanak tanır . Örneğin, pages/posts/[id].js
gibi gibi
Dışarıdan gelecek olan veri bu id değerine bağlı olarak değişkenlik gösterecektir.
Elimizde www.kubilaybozak.com/posts/1 adında bir sayfamız olduğunu varsayalım bu sayfa için sadece linke tıklandığı zaman pre render olmasıını isteyelim.
Bu tarz durumlarda bizim sayfalarımız veriye bağlı olarak render edilir.
Bu gibi durumlar için Next.js, dinamik bir sayfadan (bahsedilen [post].js ) çağrılan async ve export edilmesi gereken getStaticPath isimli bir fonksiyon kullanır.
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
Yukarıda öncelikle postları çektik daha sonra map ile id’lere göre sayfalar oluşturmamız gerekiyor .
function Post({ post }) {
// Render post...
}export async function getStaticPaths() {
// ...
}// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json() // Pass post data to the page via props
return { props: { post } }
}export default Post
Daha sonra bu konuların detayına gireceğiz şimdi sıra Server Side Rendering kısmında.
Server Side Rendering
Bir sayfa Server-side Rendering, her istekte sayfa HTML’si oluşturulur .
Bir sayfa için Server-side Rendering kullanmak için adlı export
edilen async
bir fonksiyon olan getServerSideProp
foksiyonuna ihtiyacınız vardır .Bu işlev, her istekte sunucu tarafından çağrılır.
Örneğin, sayfanızın sık güncellenen verileri (harici bir API’den alınan) önceden oluşturması gerektiğini varsayalım.
function Page({ data }) {
// Render data...
}// This gets called on every request
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json() // Pass data to the page via props
return { props: { data } }
}export default Page
Gördüğünüz gibi, getServerSideProps
'e benzer getStaticProps
, ancak fark, getServerSideProps
derleme zamanı yerine her istekte çalıştırılmasıdır.
/////////////////////////////////////////////////////////////////////
Server -Side-Rendering getServerSideProps(SSR)
Eğer bir sayfa sunucu tarafında oluşturulmak isteniyorsa kullanılması gereken fonksiyon.Next.js tarafından döndürülen verileri kullanarak her istekte bu sayfayı önceden oluşturur ve tarayıcı tarafına datalar ile beraber .
getServerSideProps
yalnızca sunucu tarafında çalışır ve hiçbir zaman tarayıcıda çalışmaz.- Bir sayfayı doğrudan request yollandığı zaman getServerSideProps istek zamanında çalışır ve return edilen propslara göre sayfa oluşturulur.
- sadece page klasörü altında bulunan .js .jsx .tsx gibi dosyalarda kullanılabilir .
export async function getServerSideProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
Parametre olarak verilen context
, aşağıdaki anahtarları içeren bir nesnedir:
params
: Bu sayfa dinamik bir rota kullanıyorsa ,params
rota parametrelerini içerir. Sayfa adı ise[id].js
,params
şöyle görünecektir{ id: ... }
query
: Dinamik yol parametreleri dahil, sorgu dizesini temsil eden bir nesne.locale
etkin yerel ayarı içerir (etkinleştirilmişse).locales
desteklenen tüm yerel ayarları içerir (etkinleştirilmişse).defaultLocale
yapılandırılmış varsayılan yerel ayarı içerir (etkinleştirilmişse).
Return etmesi gereken değerler .
Mutlaka bir değer return etmesi gerekir genelde bu değerler dinamik olan değerler olur yukarıda bahsettiğimiz [1.js, 2.js 3.js gibi gibi ]
props
, her değerin sayfa bileşeni tarafından alındığı bir anahtar/değer çiftidir mesela id vb. gibi datlar .
export async function getServerSideProps({ params }) {
const resp = await fetch `https://Test.com/pokemon/${params.id}.json`
);
if (!pokemon) {
return null; }
return {
props: {
pokemon: await resp.json(),
},
};}
notFound ,
Sayfanın olmaması bulunanmaması yada fetch işlemine çıkan bir hata sonucu 404 SayfanotFound
döndürmesine izin verir .
export async function getServerSideProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json() if (!data) {
return {
notFound: true,
}
} return {
props: { data }, // will be passed to the page component as props
}
}
redirect
, internal ve external kaynaklara yeniden yönlendirmeye izin verir. şekline uygun olmalıdır{ destination: string, permanent: boolean }
.HTTP
Bazı ender durumlarda, eski istemcilerin doğru şekilde yeniden yönlendirme yapması için özel bir durum kodu atamanız gerekebilir . Bu durumlarda,statusCode
mülk yerinepermanent
mülkü kullanabilirsiniz, ancak ikisini birden kullanamazsınız.
getServerSideProps’u ne zaman kullanmalıyım?
Yalnızca, verileri istek zamanında alınması gereken bir sayfa oluşturmanız gerekiyorsa kullanmalısınız.
Basit bir örnek;
function Page({ data }) {
// Render data...
}// This gets called on every request
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json() // Pass data to the page via props
return { props: { data } }
}export default P
- ****************************************************************
Static -Side-Generation getStaticProps
(SSG)
Statik olarak oluşturduğumuz sayfaların derleme sırasında otomatik olarak oluşmasını istediğimiz zaman kullandığımı bir teknik.
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
params
dinamik rotalar kullanan sayfalar için rota parametrelerini içerir . Örneğin, sayfa adı ise[id].js
şöyleparams
görünecektir{ id: ... }
.getStaticPaths
Buradan gelen bilgileri bu fonksiyonu bir sonraki konuda bahsedeceğiz.previewtrue
sayfanın Önizleme Modunda olup olmadığı veundefined
aksidir.previewData
tarafından ayarlanan önizleme verilerini içerirsetPreviewData
.locale
etkin yerel ayarı içerir (etkinleştirilmişse).locales
desteklenen tüm yerel ayarları içerir (etkinleştirilmişse).defaultLocale
yapılandırılmış varsayılan yerel ayarı içerir (etkinleştirilmişse).
getStaticProps return değerleri
props
, her değerin sayfa bileşeni tarafından alındığı bir anahtar/değer çiftidir.
export async function getStaticProps({ params }) {const resp = await fetch(`test.com/pokemon/${params.id}.json`);return {
props: {
pokemon: await resp.json()
},};}
revalidate
, sayfanın yeniden oluşturulmasının gerçekleşebileceği saniye cinsinden miktardır (varsayılanıfalse
yeniden doğrulamadır veya yeniden doğrulama yoktur).
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json() return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
notFound ,
Sayfanın olmaması bulunanmaması yada fetch işlemine çıkan bir hata sonucu 404 SayfanotFound
döndürmesine izin verir .
export async function getStaticProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()if (!data) {
return {
notFound: true,
}
}return {
props: { data }, // will be passed to the page component as props
}
}
redirect
, internal ve external kaynaklara yeniden yönlendirmeye izin verir. şekline uygun olmalıdır{ destination: string, permanent: boolean }
.HTTP
Bazı ender durumlarda, eski istemcilerin doğru şekilde yeniden yönlendirme yapması için özel bir durum kodu atamanız gerekebilir . Bu durumlarda,statusCode
mülk yerinepermanent
mülkü kullanabilirsiniz, ancak ikisini birden kullanamazsınız.
getStaticPaths
Bir sayfanın Dinamik Rotaları (pokemon/[id].js gibi ) varsa ve kullanıyorsa getStaticProps
, statik olarak oluşturulacak yolların bir listesini tanımlaması gerekir.
Next.js tarafından belirtilen tüm yolları statik olarak önceden işler
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
fallback: false, // can also be true or 'blocking'
}
}
Basit bir önek kod .
// pages/posts/[id].js// Generates `/posts/1` and `/posts/2`
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
fallback: false, // can also be true or 'blocking'
}
}// `getStaticPaths` requires using `getStaticProps`
export async function getStaticProps(context) {
return {
// Passed to the page component as props
props: { post: {} },
}
}export default function Post({ post }) {
// Render post...
}
getStaticPaths’i ne zaman kullanmalıyım?
Dinamik yolları kullanan getStaticPaths
sayfaları statik olarak önceden oluşturuyorsanız ve şunları kullanmalısınız:
- Veriler headless CMS’den geliyor ise
- Veriler bir veritabanından geliyor ise
- Veriler dosya sisteminden geliyor ise
- Veriler herkese açık olarak önbelleğe alınabiliyor ise (kullanıcıya özel değil)
getStaticPaths return değerleri
Örneğin, adında Dinamik Rotalar kullanan bir sayfanız olduğunu varsayalım pages/posts/[id].js
.
params
nesnenin değeri, sayfa adında kullanılan parametrelerle eşleşmelidir:- fallback
— 3 Farklı değer alır bu falback fonksiyonu.
False: Statik olarak oluşmayan sayfalar 404 hata mesajı döndürür. Sık sık yeni sayfalar eklenmiyor ise kullanışlı bir durumdur tam dersi durum için pek önerilmez. Eğer daha fazla yol eklenmesi gibi durumlar söz konusu olursa ve fallback değerinin false ise projenizi yeniden build etmeniz gerekecek.
True: uygulamanızın verilere bağlı çok sayıda statik sayfası varsa (çok büyük bir e-ticaret sitesi gibi) kullanışlıdır. Tüm ürün sayfalarını önceden oluşturmak istiyorsanız, derlemeler çok uzun zaman alacaktır.
Ek bilgiler :getStaticProps
eğer fallback: true ise
kullanırken arka planda çalışırgetStaticPaths'i getServerSideProps ile kullanamazsınız.
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// with i18n configured the locale for the path can be returned as well
locale: "en",
},
],
fallback: ...
}
Regeneration (revalidate)
Basitçe [id].js olarak tanımlı bir site düşünelim bu sitede ekranda değişen veriler var ise bu verilerin ekrana yansıtmamız gerekiyor . Mesela bir döviz tablosu real time olarak değişem değerlere sahip bu gibi durumlarda server tarafından render alınan sayfaların yenilenmesi için gerekli olan durum.
Next.js, sitenizi oluşturduktan sonra statik sayfalar oluşturmanıza veya güncellemenize olanak tanır . Artımlı Statik Yenileme (ISR), sitenin tamamını yeniden oluşturmaya gerek kalmadan sayfa başına statik oluşturmayı kullanmanıza olanak tanır . ISR ile, milyonlarca sayfaya ölçeklerken statikin avantajlarını koruyabilirsiniz
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json() return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// the path has not been generated.
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json() // Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
})) // We'll pre-render only these paths at build time.
// { fallback: blocking } will server-render pages
// on-demand if the path doesn't exist.
return { paths, fallback: 'blocking' }
}export default Blog
Oluşturma sırasında önceden oluşturulmuş bir sayfaya istek yapıldığında, başlangıçta önbelleğe alınmış sayfayı gösterecektir.
- İlk istekten sonra ve 10 saniyeden önce sayfaya yapılan tüm istekler de önbelleğe alınır ve anında gerçekleşir.
- 10 saniyelik pencereden sonra, bir sonraki istek önbelleğe alınmış (eski) sayfayı göstermeye devam edecektir.
- Next.js, arka planda sayfanın yenilenmesini tetikler.
- Sayfa başarıyla oluşturulduktan sonra, Next.js önbelleği geçersiz kılar ve güncellenen sayfayı gösterir. Arka plan yenileme başarısız olursa, eski sayfa değişmeden kalır.
Next.js, belirli bir sayfa için Next.js önbelleğini manuel olarak temizlemek için İsteğe Bağlı Artımlı Statik Yenilemeyi destekler. Bu, aşağıdaki durumlarda sitenizi güncellemeyi kolaylaştırır:
- Başsız CMS’nizden içerik oluşturulur veya güncellenir
- E-ticaret meta veri değişiklikleri (fiyat, açıklama, kategori, incelemeler vb.)
Client-side Rendering
İstemci tarafı veri alma, sayfanız SEO indekslemesi gerektirmediğinde, verilerinizi önceden oluşturmanız gerekmediğinde veya sayfalarınızın içeriğinin sık sık güncellenmesi gerektiğinde kullanışlıdır. Sunucu tarafı işleme API’lerinden farklı olarak, bileşen düzeyinde istemci tarafı veri getirmeyi kullanabilirsiniz.
Sayfa düzeyinde yapılırsa, veriler çalışma zamanında getirilir ve veriler değiştikçe sayfanın içeriği güncellenir. Bileşen düzeyinde kullanıldığında, veriler bileşen montajı sırasında alınır ve bileşenin içeriği, veriler değiştikçe güncellenir.
İstemci tarafında veri getirmeyi kullanmanın, uygulamanızın performansını ve sayfalarınızın yüklenme hızını etkileyebileceğini unutmamak önemlidir. Bunun nedeni, veri alma işleminin bileşen veya sayfalar monte edildiğinde yapılması ve verilerin önbelleğe alınmamasıdır.
function Profile() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false) useEffect(() => {
setLoading(true)
fetch('/api/profile-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, []) if (isLoading) return <p>Loading...</p>
if (!data) return <p>No profile data</p> return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}