Yayınlanma tarihi: 6 Şubat 2019, Son güncelleme tarihi: 5 Ocak 2026
Web geliştiricilerin alması gereken temel kararlardan biri, uygulamalarında mantık ve oluşturma işlemlerini nerede uygulayacaklarıdır. Web sitesi oluşturmanın pek çok yolu olduğundan bu işlem zor olabilir.
Bu alandaki anlayışımız, son birkaç yıldır Chrome'da büyük sitelerle yaptığımız çalışmalardan edinilmiştir. Genel olarak, geliştiricileri tam hidrasyon yaklaşımı yerine sunucu tarafı oluşturma veya statik oluşturma yöntemlerini kullanmaya teşvik ediyoruz.
Bu kararı verirken aralarından seçim yaptığımız mimarileri daha iyi anlamak için tutarlı bir terminolojiye ve her yaklaşım için ortak bir çerçeveye ihtiyacımız var. Ardından, her bir oluşturma yaklaşımının avantaj ve dezavantajlarını sayfa performansı açısından daha iyi değerlendirebilirsiniz.
Terminoloji
Öncelikle, kullanacağımız bazı terimleri tanımlayalım.
Oluşturma
- Sunucu tarafı oluşturma (SSR)
- İstemciye JavaScript yerine HTML göndermek için uygulamayı sunucuda oluşturma.
- İstemci taraflı oluşturma (CSR)
- DOM'u değiştirmek için JavaScript kullanarak bir uygulamayı tarayıcıda oluşturma.
- Önceden işleme
- İlk durumunu statik HTML olarak yakalamak için derleme sırasında istemci tarafı bir uygulama çalıştırma. Bu anlamdaki "önceden oluşturma"nın, gelecekteki gezinmelerin tarayıcıda önceden oluşturulmasından farklı olduğunu unutmayın.
- Sıvı alımı
- Sunucu tarafında oluşturulan HTML'ye uygulama durumu ve etkileşim eklemek için istemci tarafı komut dosyalarını çalıştırma. Hidrasyon işlemi, DOM'un değişmediğini varsayar.
- Rehidrasyon
- Genellikle hidrasyon ile aynı anlamda kullanılsa da yeniden hidrasyon, ilk hidrasyondan sonra da dahil olmak üzere DOM'un en son durumla düzenli olarak güncellenmesini ifade eder.
Performans
- Time to First Byte (TTFB)
- Bir bağlantının tıklanması ile yeni sayfada yüklenen içeriğin ilk baytı arasındaki süre.
- First Contentful Paint (FCP)
- İstenen içeriğin (makale gövdesi vb.) görünür hale geldiği zaman.
- Interaction to Next Paint (INP)
- Bir sayfanın kullanıcı girişlerine tutarlı bir şekilde hızlı yanıt verip vermediğini değerlendiren temsili bir metrik.
- Toplam Engelleme Süresi (TBT)
- Sayfa yükleme sırasında ana iş parçacığının ne kadar süreyle engellendiğini hesaplayan INP için bir vekil metrik.
Sunucu tarafı oluşturma
Sunucu tarafı oluşturma, gezinmeye yanıt olarak sunucudaki bir sayfanın tam HTML'sini oluşturur. Oluşturucu, tarayıcı yanıt almadan önce bu işlemleri gerçekleştirdiği için istemcide veri getirme ve şablon oluşturma işlemleri için ek gidiş dönüşler önlenir.
Sunucu taraflı oluşturma genellikle hızlı bir FCP sağlar. Sayfa mantığını sunucuda çalıştırmak ve sunucuda oluşturmak, istemciye çok fazla JavaScript göndermenizi önler. Bu, bir sayfanın TBT'sini azaltmaya yardımcı olur. Ana iş parçacığı, sayfa yükleme sırasında daha az sıklıkta engellendiğinden bu durum, INP'nin düşmesine de yol açabilir. Ana iş parçacığı daha az sıklıkta engellendiğinde kullanıcı etkileşimlerinin daha erken çalışması için daha fazla fırsat olur.
Sunucu tarafında oluşturma işleminde, kullanıcı tarayıcısına yalnızca metin ve bağlantılar gönderdiğiniz için bu durum mantıklıdır. Bu yaklaşım, çeşitli cihaz ve ağ koşullarında iyi sonuç verebilir ve doküman ayrıştırmayı yayınlama gibi ilginç tarayıcı optimizasyonları sunar.
Sunucu tarafında oluşturma sayesinde kullanıcıların, sitenizi kullanabilmek için CPU'ya bağlı JavaScript'in çalışmasını bekleme olasılığı daha düşüktür. Üçüncü taraf JavaScript'i önleyemediğiniz durumlarda bile, kendi birinci taraf JavaScript maliyetlerinizi azaltmak için sunucu tarafı oluşturma kullanmak, geri kalan için daha fazla bütçe elde etmenizi sağlayabilir. Ancak bu yaklaşımla ilgili olası bir dezavantaj vardır: Sunucuda sayfa oluşturmak zaman alır ve bu da sayfanızın TTFB'sini artırabilir.
Sunucu tarafı oluşturmanın uygulamanız için yeterli olup olmadığı büyük ölçüde oluşturduğunuz deneyimin türüne bağlıdır. Sunucu tarafında oluşturma ile istemci tarafında oluşturmanın doğru uygulamaları konusunda uzun süredir devam eden bir tartışma olsa da bazı sayfalar için sunucu tarafında oluşturmayı, bazıları için ise istemci tarafında oluşturmayı kullanmayı tercih edebilirsiniz. Bazı siteler, karma oluşturma tekniklerini başarıyla kullanmaktadır. Örneğin, Netflix, nispeten statik açılış sayfalarını sunucu tarafında oluştururken etkileşim yoğun sayfalar için JavaScript'i prefetching. Bu sayede, istemci tarafında oluşturulan daha ağır sayfaların hızlı yüklenme olasılığı artar.
Birçok modern çerçeve, kitaplık ve mimariyle aynı uygulamayı hem istemcide hem de sunucuda oluşturabilirsiniz. Bu teknikleri sunucu tarafında oluşturma için kullanabilirsiniz. Ancak oluşturma işleminin hem sunucuda hem de istemcide gerçekleştiği mimariler, çok farklı performans özelliklerine ve ödünleşimlere sahip kendi çözüm sınıfını oluşturur. React kullanıcıları, sunucu tarafı oluşturma için sunucu DOM API'lerini veya Next.js gibi bu API'ler üzerinde oluşturulmuş çözümleri kullanabilir. Vue kullanıcıları, Vue'nun sunucu taraflı oluşturma kılavuzunu veya Nuxt'ı kullanabilir. Angular'da Universal bulunur.
Ancak en popüler çözümlerin çoğu bir tür hidrasyon kullandığından aracınızın kullandığı yaklaşımlara dikkat edin.
Statik oluşturma
Statik oluşturma derleme sırasında gerçekleşir. Bu yaklaşım, sayfalarınızdaki istemci tarafı JavaScript miktarını sınırladığınız sürece hızlı bir FCP'nin yanı sıra daha düşük bir TBT ve INP sunar. Sunucu tarafında oluşturma işleminden farklı olarak, bir sayfanın HTML'sinin sunucuda dinamik olarak oluşturulması gerekmediğinden tutarlı bir şekilde hızlı TTFB elde edilir. Genel olarak statik oluşturma, her URL için önceden ayrı bir HTML dosyası oluşturmak anlamına gelir. Önceden oluşturulmuş HTML yanıtlarıyla, uç önbelleğe almadan yararlanmak için statik oluşturmaları birden fazla CDN'ye dağıtabilirsiniz.
Statik oluşturma çözümleri her şekil ve boyutta olabilir. Gatsby gibi araçlar, geliştiricilerin uygulamalarının derleme adımı olarak oluşturulmadığını, dinamik olarak oluşturulduğunu hissetmesini sağlamak için tasarlanmıştır. 11ty, Jekyll ve Metalsmith gibi statik site oluşturma araçları, statik doğalarını benimseyerek daha şablon odaklı bir yaklaşım sunar.
Statik oluşturmanın dezavantajlarından biri, olası her URL için ayrı HTML dosyaları oluşturmasıdır. Bu URL'leri önceden tahmin etmeniz gerektiğinde ve çok sayıda benzersiz sayfa içeren sitelerde bu işlem zor hatta imkansız olabilir.
React kullanıcıları, bileşenlerden sayfa oluşturmayı kolaylaştıran Gatsby, Next.js static export veya Navi'ye aşina olabilir. Ancak statik oluşturma ve önceden oluşturma farklı şekilde çalışır: Statik olarak oluşturulan sayfalar, istemci tarafında çok fazla JavaScript yürütülmesine gerek kalmadan etkileşimli hale gelir. Önceden oluşturma ise sayfaların gerçekten etkileşimli olması için istemcide başlatılması gereken tek sayfalık bir uygulamanın FCP'sini iyileştirir.
Belirli bir çözümün statik oluşturma mı yoksa önceden işleme mi olduğundan emin değilseniz JavaScript'i devre dışı bırakmayı ve test etmek istediğiniz sayfayı yüklemeyi deneyin. Statik olarak oluşturulan sayfalarda, etkileşimli özelliklerin çoğu JavaScript olmadan da kullanılabilir. Önceden işlenmiş sayfalarda, JavaScript'in devre dışı bırakıldığı bağlantılar gibi bazı temel özellikler bulunabilir ancak sayfanın çoğu etkisizdir.
Bir başka yararlı test de Chrome Geliştirici Araçları'nda ağ sınırlaması kullanıp bir sayfa etkileşimli hale gelmeden önce ne kadar JavaScript indirildiğini görmektir. Önceden oluşturma genellikle etkileşimli hale gelmek için daha fazla JavaScript gerektirir ve bu JavaScript, statik oluşturmada kullanılan ilerleyici geliştirme yaklaşımından daha karmaşık olma eğilimindedir.
Sunucu tarafı oluşturma ve statik oluşturma karşılaştırması
Dinamik yapısı nedeniyle önemli bilgi işlem ek yükü maliyetlerine yol açabileceğinden sunucu tarafı oluşturma, her şey için en iyi çözüm değildir. Birçok sunucu tarafı oluşturma çözümü, erken boşaltma yapmaz, TTFB'yi geciktirir veya gönderilen verileri iki katına çıkarır (ör. istemcide JavaScript tarafından kullanılan satır içi durumlar). React'te,
renderToString() senkron ve tek iş parçacıklı olduğundan yavaş olabilir.
Daha yeni React sunucu DOM API'leri, akışı destekler. Bu sayede, HTML yanıtının ilk kısmı sunucuda oluşturulmaya devam ederken tarayıcıya daha hızlı ulaşabilir.
Sunucu taraflı oluşturmayı "doğru" yapmak, bileşen önbelleğe alma için bir çözüm bulmayı veya oluşturmayı, bellek tüketimini yönetmeyi, memoization tekniklerini kullanmayı ve diğer konuları içerebilir. Aynı uygulamayı genellikle iki kez işliyor veya yeniden oluşturuyorsunuz. Bir kez istemcide, bir kez de sunucuda. İçeriği daha hızlı gösteren sunucu tarafında oluşturma, yapmanız gereken işi azaltmayabilir. Sunucu tarafından oluşturulan bir HTML yanıtı istemciye ulaştıktan sonra istemcide çok fazla işiniz varsa bu durum, web siteniz için yine daha yüksek TBT ve INP değerlerine yol açabilir.
Sunucu tarafı oluşturma, her URL için isteğe bağlı olarak HTML oluşturur ancak yalnızca statik olarak oluşturulmuş içerik sunmaktan daha yavaş olabilir. Ekstra çaba gösterebilirseniz sunucu tarafı oluşturma ve HTML önbelleğe alma, sunucu oluşturma süresini önemli ölçüde azaltabilir. Sunucu tarafında oluşturmanın avantajı, daha fazla "canlı" veri çekebilme ve statik oluşturmayla mümkün olandan daha eksiksiz bir istek grubuna yanıt verebilme olanağıdır. Kişiselleştirme gerektiren sayfalar, statik oluşturma ile iyi çalışmayan istek türünün somut bir örneğidir.
Sunucu tarafında oluşturma, PWA oluştururken de ilginç kararlar vermenize neden olabilir. Tam sayfa hizmet çalışanı önbelleğe alma mı yoksa içeriklerin tek tek sunucu tarafında oluşturulması mı daha iyidir?
İstemci tarafı oluşturma
İstemci taraflı oluşturma, sayfaların doğrudan tarayıcıda JavaScript ile oluşturulması anlamına gelir. Tüm mantık, veri getirme, şablon oluşturma ve yönlendirme işlemleri sunucuda değil istemcide yapılır. Sonuç olarak, sunucudan kullanıcının cihazına daha fazla veri aktarılır ve bu durumun kendi içinde bazı dezavantajları vardır.
İstemci tarafı oluşturma, mobil cihazlar için hızlı bir şekilde oluşturulup korunması zor olabilir.
Sıkı bir JavaScript bütçesi oluşturmak ve mümkün olduğunca az gidiş-dönüş ile değer sunmak için biraz çalışarak istemci tarafında oluşturmanın performansını neredeyse tamamen sunucu tarafında oluşturmanın performansına eşleyebilirsiniz. <link rel=preload> kullanarak kritik komut dosyalarını ve verileri sunarak ayrıştırıcının sizin için daha hızlı çalışmasını sağlayabilirsiniz.
İlk ve sonraki gezinmelerin anlık olmasını sağlamak için PRPL gibi kalıpları kullanmayı da düşünebilirsiniz.
İstemci tarafında oluşturmanın temel dezavantajı, gereken JavaScript miktarının uygulama büyüdükçe artma eğiliminde olmasıdır. Bu durum, sayfanın INP'sini etkileyebilir. Bu durum, özellikle işlem gücü için rekabet eden ve genellikle bir sayfanın içeriği oluşturulmadan önce işlenmesi gereken yeni JavaScript kitaplıklarının, polyfill'lerin ve üçüncü taraf kodlarının eklenmesiyle daha da zorlaşır.
İstemci tarafında oluşturma kullanan ve büyük JavaScript paketlerine dayanan deneyimler, sayfa yükleme sırasında TBT ve INP'yi düşürmek için agresif kod bölme ve yalnızca kullanıcının ihtiyaç duyduğu şeyleri ihtiyaç duyduğu anda sunmak için JavaScript'i geç yükleme yöntemini kullanmalıdır. Etkileşimin az olduğu veya hiç olmadığı deneyimlerde, sunucu tarafı oluşturma bu sorunlara daha ölçeklenebilir bir çözüm sunabilir.
Tek sayfalık uygulamalar oluşturanlar için, kullanıcı arayüzünün çoğu sayfa tarafından paylaşılan temel kısımlarını belirlemek, uygulama kabuğu önbelleğe alma tekniğini uygulamanıza olanak tanır. Bu özellik, hizmet çalışanlarıyla birlikte kullanıldığında tekrarlanan ziyaretlerde algılanan performansı önemli ölçüde artırabilir. Bunun nedeni, sayfanın uygulama kabuğu HTML'sini ve bağımlılıklarını CacheStorage'dan çok hızlı bir şekilde yükleyebilmesidir.
Yeniden hidrasyon, sunucu tarafı ve istemci tarafı oluşturmayı birleştirir.
Hidrasyon hem istemci tarafı hem de sunucu tarafı oluşturma işlemlerini yaparak bu iki yöntem arasındaki dengeyi korumaya yardımcı olan bir yaklaşımdır. Tam sayfa yükleme veya yeniden yükleme gibi gezinme istekleri, uygulamayı HTML'ye dönüştüren bir sunucu tarafından işlenir. Ardından, oluşturma için kullanılan JavaScript ve veriler, sonuçta ortaya çıkan dokümana yerleştirilir. Dikkatli bir şekilde yapıldığında bu işlem, sunucu tarafı oluşturma gibi hızlı bir FCP elde eder ve ardından istemcide tekrar oluşturarak "devam eder".
Bu etkili bir çözüm olsa da performans açısından önemli dezavantajları olabilir.
Yeniden hidrasyonla sunucu tarafında oluşturmanın temel dezavantajı, FCP'yi iyileştirse bile TBT ve INP üzerinde önemli bir olumsuz etkiye sahip olabilmesidir. Sunucu tarafında oluşturulan sayfalar yüklenmiş ve etkileşimli gibi görünebilir ancak bileşenlerin istemci tarafı komut dosyaları yürütülüp etkinlik işleyicileri eklenene kadar girişe yanıt veremez. Mobil cihazlarda bu işlem dakikalar sürebilir ve kullanıcıların kafasını karıştırıp sinirlendirebilir.
Yeniden etkinleştirme sorunu: İki uygulama fiyatına tek uygulama
İstemci tarafındaki JavaScript'in, sunucunun HTML'sini oluşturduğu tüm verileri yeniden istemeden sunucunun bıraktığı yerden doğru bir şekilde devam edebilmesi için çoğu sunucu tarafı oluşturma çözümü, bir kullanıcı arayüzünün veri bağımlılıklarından gelen yanıtı belgedeki komut dosyası etiketleri olarak serileştirir. Bu işlem çok fazla HTML'yi kopyaladığından yeniden hidrasyon, yalnızca etkileşimde gecikme sorununa değil, başka sorunlara da neden olabilir.
Sunucu, bir gezinme isteğine yanıt olarak uygulamanın kullanıcı arayüzünün açıklamasını döndürüyor ancak bu kullanıcı arayüzünü oluşturmak için kullanılan kaynak verileri ve kullanıcı arayüzünün istemcide başlatılan uygulamasının tam bir kopyasını da döndürüyor. bundle.js yüklenip yürütülene kadar kullanıcı arayüzü etkileşimli hale gelmez.
Sunucu tarafı oluşturma ve yeniden hidrasyon kullanan gerçek web sitelerinden toplanan performans metrikleri, bu yöntemin nadiren en iyi seçenek olduğunu gösteriyor. En önemli neden, sayfa hazır görünürken etkileşimli özelliklerinin hiçbirinin çalışmaması durumunda kullanıcı deneyimi üzerindeki etkisidir.
Yeniden hidrasyonla sunucu tarafı oluşturma umudu var. Kısa vadede, yalnızca yüksek oranda önbelleğe alınabilir içerik için sunucu tarafında oluşturma kullanmak TTFB'yi azaltabilir ve önceden işleme benzer sonuçlar üretebilir. Bu tekniğin gelecekte daha uygulanabilir olması için kademeli, aşamalı veya kısmi olarak yeniden nemlendirme yapılması gerekebilir.
Sunucu taraflı oluşturmayı yayınlama ve aşamalı olarak yeniden doldurma
Sunucu tarafında oluşturma, son birkaç yılda çeşitli gelişmeler yaşadı.
Akışlı sunucu tarafı oluşturma, tarayıcının alındıkça aşamalı olarak oluşturabileceği parçalar halinde HTML göndermenize olanak tanır. Bu sayede, işaretlemeyi kullanıcılarınıza daha hızlı ulaştırabilir ve FCP'nizi hızlandırabilirsiniz. React'te, renderToPipeableStream() içinde akışların eşzamansız olması, eşzamanlı renderToString() ile karşılaştırıldığında geri basıncın iyi şekilde işlendiği anlamına gelir.
Aşamalı yeniden hidrasyon da dikkate alınması gereken bir tekniktir (React bunu uygulamıştır). Bu yaklaşımla, sunucu tarafında oluşturulan bir uygulamanın parçaları, uygulamanın tamamını tek seferde başlatma şeklindeki mevcut yaygın yaklaşımın aksine zaman içinde "başlatılır". Bu sayede, sayfanın düşük öncelikli bölümlerinin istemci tarafında yükseltilmesi ertelenebilir. Bu da ana iş parçacığının engellenmesini önleyerek sayfaların etkileşimli hale gelmesi için gereken JavaScript miktarını azaltır ve kullanıcı etkileşimlerinin kullanıcı tarafından başlatıldıktan sonra daha hızlı gerçekleşmesini sağlar.
Aşamalı yeniden hidrasyon, sunucu tarafında oluşturma yeniden hidrasyonuyla ilgili en yaygın sorunlardan birini önlemenize de yardımcı olabilir: Sunucuda oluşturulan bir DOM ağacı, genellikle ilk eşzamanlı istemci tarafında oluşturma işlemi henüz hazır olmayan veriler (ör. henüz çözülmemiş bir Promise) gerektirdiğinden yok edilir ve hemen yeniden oluşturulur.
Kısmi rehidrasyon
Kısmi rehidrasyonun uygulanması zor olmuştur. Bu yaklaşım, sayfanın tek tek parçalarını (bileşenler, görünümler veya ağaçlar) analiz eden ve az etkileşimli ya da hiç etkileşimli olmayan parçaları tanımlayan aşamalı yeniden hidrasyonun bir uzantısıdır. Çoğunlukla statik olan bu kısımların her biri için ilgili JavaScript kodu daha sonra etkisiz referanslara ve dekoratif özelliklere dönüştürülerek istemci tarafındaki ayak izi neredeyse sıfıra indirilir.
Kısmi yeniden hidrasyon yaklaşımının kendine özgü sorunları ve tavizleri vardır. Bu durum, önbelleğe alma konusunda bazı ilginç zorluklar yaratır. İstemci taraflı gezinme, uygulamanın etkileşimsiz bölümleri için sunucu taraflı oluşturulan HTML'nin tam sayfa yüklemesi olmadan kullanılabileceği anlamına gelmez.
Trisomorphic oluşturma
Service worker kullanabiliyorsanız trisomorphic oluşturmayı değerlendirin. Bu teknik, ilk veya JavaScript içermeyen gezinmeler için akış sunucu tarafında oluşturmayı kullanmanıza ve ardından hizmet çalışanınızın, yüklendikten sonraki gezinmeler için HTML oluşturmayı devralmasına olanak tanır. Bu sayede, önbelleğe alınmış bileşenler ve şablonlar güncel tutulabilir ve aynı oturumda yeni görünümler oluşturmak için SPA tarzı gezinmeler etkinleştirilebilir. Bu yaklaşım, sunucu, istemci sayfası ve hizmet çalışanı arasında aynı şablon oluşturma ve yönlendirme kodunu paylaşabildiğinizde en iyi sonucu verir.
SEO ile ilgili dikkat edilmesi gereken noktalar
Web oluşturma stratejisi seçerken ekipler genellikle SEO'nun etkisini göz önünde bulundurur. Sunucu tarafı oluşturma, tarayıcıların yorumlayabileceği "eksiksiz görünen" bir deneyim sunmak için popüler bir seçimdir. Tarayıcılar JavaScript'i anlayabilir ancak genellikle oluşturma şekilleriyle ilgili sınırlamalar vardır. İstemci tarafında oluşturma işe yarayabilir ancak genellikle ek test ve ek yük gerektirir. Daha yakın bir zamanda, mimariniz büyük ölçüde istemci tarafı JavaScript'e bağlıysa dinamik oluşturma da dikkate alınması gereken bir seçenek haline geldi.
Sonuç
Oluşturma yaklaşımına karar verirken darboğazlarınızı ölçün ve anlayın. Statik oluşturma veya sunucu tarafı oluşturma yöntemlerinin sizi hedefinize ulaştırıp ulaştıramayacağını değerlendirin. Etkileşimli bir deneyim sunmak için çoğunlukla HTML ve minimum JavaScript gönderebilirsiniz. Sunucu-istemci spektrumunu gösteren faydalı bir infografik:
Kredi
Yorumları ve ilhamları için herkese teşekkür ederiz:
Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson ve Sebastian Markbåge.