Web'de oluşturma

Yayınlanma tarihi: 6 Şubat 2019, Son güncelleme tarihi: 5 Ocak 2026

Web geliştiricilerinin vermesi 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ğu için bu zor olabilir.

Bu konudaki anlayışımız, son birkaç yıldır Chrome'da büyük sitelerle yaptığımız görüşmelerden edindiğimiz bilgilere dayanıyor. Genel olarak geliştiricilerin, tam yeniden hidrasyon yaklaşımı yerine sunucu tarafı oluşturma veya statik oluşturma yöntemlerini kullanmalarını öneririz.

Bu kararı verirken seçtiğimiz mimarileri daha iyi anlamak için her yaklaşım için tutarlı bir terminolojiye ve 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 sunucuda bir uygulama 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ı uygulaması çalıştırma. Bu anlamda "önceden işleme"nin, gelecekteki gezinmelerin tarayıcı tarafından önceden işlenmesinden farklı olduğunu unutmayın.
Sıvı alımı
Sunucu tarafından oluşturulan HTML'ye uygulama durumu ve etkileşim eklemek için istemci tarafı komut dosyaları çalıştırma. Hidrasyon, 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üncellenmesi anlamına gelir.

Performans

Time to First Byte (TTFB)
Bir bağlantının tıklanması ile yeni sayfadaki ilk içerik baytının yüklenmesi arasında geçen 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 metriktir.
Total Blocking Time (TBT)
Sayfa yükleme sırasında ana iş parçacığının ne kadar süre engellendiğini hesaplayan INP için proxy metriği.

Sunucu tarafı oluşturma

Sunucu taraflı oluşturma, gezinmeye yanıt olarak sunucudaki bir sayfanın tam HTML'sini oluşturur. Bu sayede, oluşturucu tarayıcı yanıt almadan önce bunları işlediğ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ı ve oluşturma işlemini sunucuda çalıştırmak, istemciye çok fazla JavaScript göndermenizi önler. Bu, sayfanın TBT'sini azaltmaya yardımcı olur. Bu da sayfa yükleme sırasında ana iş parçacığı sık sık engellenmediği için INP'nin düşmesine neden olabilir. Ana iş parçacığı daha az engellendiğinde kullanıcı etkileşimlerinin daha erken çalıştırılma olasılığı artar.

Sunucu tarafı oluşturma ile kullanıcının tarayıcısına yalnızca metin ve bağlantı gönderdiğiniz için bu mantıklıdır. Bu yaklaşım, çeşitli cihaz ve ağ koşullarında iyi sonuç verebilir ve doküman ayrıştırma akışı gibi ilginç tarayıcı optimizasyonları sağlar.

Sunucu tarafı oluşturma ve JavaScript yürütmenin FCP ve TTI'yı etkilediğini gösteren diyagram.
Sunucu tarafı oluşturma ile FCP ve TTI.

Sunucu tarafı 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'ten kaçınamasanız bile kendi birinci taraf JavaScript maliyetlerinizi azaltmak için sunucu tarafı oluşturmayı kullanmak, geri kalanı için size daha fazla bütçe sağlayabilir. Ancak bu yaklaşımın 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 ne tür bir deneyim oluşturduğunuza 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 vardır ancak bazı sayfalar için sunucu tarafında oluşturmayı kullanmayı, diğerleri için kullanmamayı her zaman seçebilirsiniz. Bazı siteler, karma oluşturma tekniklerini başarıyla uygulamıştır. Örneğin, Netflix nispeten statik açılış sayfalarını sunucu tarafında oluştururken etkileşimin yoğun olduğu sayfalar için JavaScript'i prefetching. Bu sayede, istemci tarafında oluşturulan bu daha ağır sayfaların hızlı yüklenme olasılığı artar.

Birçok modern çerçeve, kitaplık ve mimari sayesinde aynı uygulamayı hem istemcide hem de sunucuda oluşturabilirsiniz. Bu teknikleri sunucu tarafı 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 avantaj/dezavantajlara sahip kendi çözüm sınıflarıdır. React kullanıcıları, sunucu tarafı oluşturma için sunucu DOM API'lerini veya Next.js gibi bu API'ler üzerine inşa edilmiş çözümleri kullanabilir. Vue kullanıcıları, Vue'nun sunucu taraflı oluşturma kılavuzunu veya Nuxt'ı kullanabilir. Angular'da Universal vardır.

Ancak en popüler çözümler bir tür hidrasyon kullanır. Bu nedenle, 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 TBT ve INP sunar. Sunucu tarafında oluşturmanın aksine, bir sayfanın HTML'sinin sunucuda dinamik olarak oluşturulması gerekmediğinden tutarlı bir şekilde hızlı TTFB elde edilir. Genellikle statik oluşturma, her URL için önceden ayrı bir HTML dosyası oluşturmak anlamına gelir. Önceden oluşturulan HTML yanıtlarıyla, uç önbelleğe alma özelliğinden yararlanmak için statik oluşturmaları birden fazla CDN'ye dağıtabilirsiniz.

Statik oluşturmayı ve FCP ile TTI'yı etkileyen isteğe bağlı JavaScript yürütmeyi gösteren şema.
Statik oluşturma ile FCP ve TTI.

Statik oluşturma için çeşitli çözümler mevcuttur. Gatsby gibi araçlar, geliştiricilere uygulamalarının bir derleme adımı olarak oluşturulmadığını, dinamik olarak oluşturulduğunu hissettirmek için tasarlanmıştır. 11ty, Jekyll ve Metalsmith gibi statik site oluşturma araçları, statik yapılarını benimseyerek daha çok şablon odaklı bir yaklaşım sunar.

Statik oluşturmanın dezavantajlarından biri, olası her URL için ayrı HTML dosyaları oluşturması gerekmesidir. Bu URL'leri önceden tahmin etmeniz gerektiğinde ve çok sayıda benzersiz sayfa içeren siteler için bu işlem zor, hatta imkansız olabilir.

React kullanıcıları, bileşenlerden sayfa oluşturmayı kolaylaştıran Gatsby, Next.js statik dışa aktarma veya Navi'ye aşina olabilir. Ancak statik oluşturma ve önceden işleme farklı şekilde davranır: Statik olarak oluşturulan sayfalar, istemci tarafında çok fazla JavaScript yürütmeye gerek kalmadan etkileşimlidir. Önceden işleme ise sayfaları gerçekten etkileşimli hale getirmek için istemcide başlatılması gereken tek sayfalık 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 çalışır. Önceden işlenmiş sayfalarda, JavaScript devre dışı bırakılmış bağlantılar gibi bazı temel özellikler hâlâ bulunabilir ancak sayfanın çoğu etkin değildir.

Yararlı bir başka test de Chrome Geliştirici Araçları'nda ağ sınırlama özelliğini kullanmak ve bir sayfa etkileşimli hale gelmeden önce ne kadar JavaScript indirildiğini görmektir. Önceden işleme, etkileşimli hale gelmek için genellikle daha fazla JavaScript gerektirir ve bu JavaScript, statik işlemede kullanılan progresif geliştirme yaklaşımından daha karmaşık olma eğilimindedir.

Sunucu tarafı oluşturma ile statik oluşturma karşılaştırması

Dinamik yapısı önemli işlem yükü maliyetlerine neden olabileceğinden, sunucu tarafı oluşturma her şey için en iyi çözüm değildir. Birçok sunucu tarafı oluşturma çözümü erken temizleme yapmaz, TTFB'yi geciktirir veya gönderilen verileri iki katına çıkarır (örneğin, istemcide JavaScript tarafından kullanılan satır içi durumlar). React'te renderToString(), eşzamanlı ve tek iş parçacıklı olduğu için yavaş olabilir. Daha yeni React sunucu DOM API'leri, akışı destekler. Bu sayede, HTML yanıtının ilk kısmı tarayıcıya daha erken ulaşırken geri kalanı sunucuda oluşturulmaya devam eder.

Sunucu taraflı oluşturmayı "doğru" şekilde uygulamak için bileşen önbelleğe alma, bellek tüketimini yönetme, not alma tekniklerini kullanma ve diğer konularla ilgili bir çözüm bulmanız veya oluşturmanız gerekebilir. Genellikle aynı uygulamayı biri istemcide, diğeri sunucuda olmak üzere iki kez işler veya yeniden oluşturursunuz. Sunucu tarafında oluşturma, içeriği daha erken gösterse de işinizi her zaman azaltmaz. Sunucu tarafından oluşturulan HTML yanıtı istemciye ulaştıktan sonra istemci tarafında çok fazla işiniz varsa bu durum web siteniz için 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 üretir ancak statik olarak oluşturulmuş içerik sunmaktan daha yavaş olabilir. Ekstra çaba harcayabilirseniz 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 çekebilmesi ve statik oluşturmaya kıyasla daha eksiksiz bir istek grubuna yanıt verebilmesidir. Kişiselleştirme gerektiren sayfalar, statik oluşturma ile iyi çalışmayan istek türüne somut bir örnektir.

Sunucu tarafı oluşturma, PWA oluştururken de ilginç kararlar sunabilir. Tam sayfa hizmet çalışanı önbelleğe alma özelliğini kullanmak mı yoksa içerik parçalarını sunucuda oluşturmak mı daha iyidir?

İstemci tarafı oluşturma

İstemci taraflı oluşturma, sayfaların JavaScript ile doğrudan tarayıcıda oluşturulması anlamına gelir. Tüm mantık, veri getirme, şablon oluşturma ve yönlendirme işlemleri sunucu yerine istemcide gerçekleştirilir. Bunun sonucunda, sunucudan kullanıcının cihazına daha fazla veri aktarılır ve bu durumun kendi dezavantajları vardır.

İstemci tarafı oluşturma işlemini mobil cihazlar için hızlı hale getirmek ve hızlı tutmak zor olabilir. JavaScript bütçesini sıkı tutmak 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, saf sunucu tarafında oluşturma performansını neredeyse kopyalamasını sağlayabilirsiniz. Kritik komut dosyalarını ve verileri <link rel=preload> kullanarak yayınlayarak ayrıştırıcının sizin için daha hızlı çalışmasını sağlayabilirsiniz. Ayrıca, ilk ve sonraki gezinmelerin anında gerçekleşmesini sağlamak için PRPL gibi kalıpları kullanmanızı öneririz.

İstemci tarafı oluşturmanın FCP ve TTI'yı etkilediğini gösteren diyagram.
İstemci tarafı oluşturma ile FCP ve TTI.

İstemci tarafı oluşturmanın temel dezavantajı, gereken JavaScript miktarının uygulama büyüdükçe artmasıdır. Bu durum, sayfanın INP'sini etkileyebilir. Bu durum, 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ı, polyfill'ler ve üçüncü taraf kodlarının eklenmesiyle özellikle zorlaşır.

İstemci tarafı oluşturma kullanan ve büyük JavaScript paketlerine dayanan deneyimler, sayfa yükleme sırasında TBT ve INP'yi azaltmak için agresif kod bölme yöntemini kullanmalıdır. Ayrıca, yalnızca kullanıcının ihtiyaç duyduğu içeriği gerektiğinde sunmak için JavaScript'i geç yüklemelidir. Etkileşimin az olduğu veya hiç olmadığı deneyimlerde, sunucu tarafı oluşturma bu sorunlar için daha ölçeklenebilir bir çözüm olabilir.

Tek sayfalık uygulamalar geliştirenler, çoğu sayfanın paylaştığı kullanıcı arayüzünün temel parçalarını belirleyerek uygulama kabuğu önbelleğe alma tekniğini uygulayabilir. Hizmet çalışanlarıyla birlikte kullanıldığında, sayfa uygulama kabuğu HTML'sini ve bağımlılıklarını CacheStorage üzerinden çok hızlı bir şekilde yükleyebileceğinden, tekrarlanan ziyaretlerde algılanan performansı önemli ölçüde artırabilir.

Yeniden canlandırma, sunucu tarafı ve istemci tarafı oluşturmayı birleştirir

Hidrasyon, hem istemci tarafında hem de sunucu tarafında oluşturma yaparak bu iki yaklaşım arasındaki dengeyi sağlayan bir yöntemdir. Tam sayfa yüklemeleri veya yeniden yüklemeler 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ç belgesine yerleştirilir. Dikkatli bir şekilde yapıldığında bu yöntem, sunucu tarafı oluşturma gibi hızlı bir FCP sağlar ve ardından istemcide tekrar oluşturarak "devam eder".

Bu etkili bir çözümdür ancak önemli performans dezavantajları olabilir.

Yeniden doldurma ile sunucu tarafı 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şenler için istemci tarafı komut dosyaları yürütülene ve etkinlik işleyiciler eklenene kadar girişe yanıt veremez. Mobil cihazlarda bu işlem dakikalar sürebilir, kullanıcıların kafasını karıştırabilir ve onları hayal kırıklığına uğratabilir.

Yeniden su ekleme sorunu: İki fiyatına bir uygulama

İstemci tarafı JavaScript'in, sunucunun HTML'sini oluşturduğu tüm verileri yeniden istemeden sunucunun kaldığı yerden doğru ş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 canlandırma gecikmeli etkileşimden daha fazla soruna neden olabilir.

Serileştirilmiş kullanıcı arayüzü, satır içi veriler ve bundle.js komut dosyası içeren HTML belgesi.

Sunucu, bir gezinme isteğine yanıt olarak uygulamanın kullanıcı arayüzünün açıklamasını döndürür. Ancak aynı zamanda bu kullanıcı arayüzünü oluşturmak için kullanılan kaynak verileri ve kullanıcı arayüzü uygulamasının tam bir kopyasını da döndürür. Bu kopya daha sonra istemcide başlatılır. bundle.js yüklenip yürütülene kadar kullanıcı arayüzü etkileşimli hale gelmez.

Sunucu tarafı oluşturma ve yeniden canlandırma kullanan gerçek web sitelerinden toplanan performans metrikleri, bu yöntemin nadiren en iyi seçenek olduğunu gösteriyor. En önemli neden, sayfanın hazır göründüğü ancak etkileşimli özelliklerinin hiçbirinin çalışmadığı durumlarda kullanıcı deneyimi üzerindeki etkisidir.

İstemci tarafı oluşturmanın TTI üzerindeki olumsuz etkileri.

Yeniden hidrasyonla sunucu tarafı oluşturma için umut var. Kısa vadede, yalnızca yüksek oranda önbelleğe alınabilir içerikler için sunucu tarafında oluşturma yöntemini kullanmak TTFB'yi azaltarak önceden işlemeye benzer sonuçlar verebilir. Yeniden canlandırmayı artımlı, aşamalı veya kısmi olarak yapmak, bu tekniği gelecekte daha uygulanabilir hale getirmenin anahtarı olabilir.

Sunucu tarafı oluşturmayı akışla aktarma ve aşamalı olarak yeniden canlandırma

Sunucu tarafı oluşturma, son birkaç yılda bir dizi gelişme kaydetti.

Akış sunucu tarafı oluşturma, HTML'yi tarayıcının alındığı gibi kademeli olarak oluşturabileceği parçalar halinde göndermenize olanak tanır. Bu sayede işaretleme, kullanıcılarınıza daha hızlı ulaşabilir ve FCP'niz hızlanabilir. React'te, akışların renderToString()'deki eşzamanlı akışlara kıyasla renderToPipeableStream()'de eşzamansız olması, geri basıncın iyi yönetildiği anlamına gelir.

Kademeli yeniden canlandırma da dikkate alınmaya değerdir (React bunu uygulamıştır). Bu yaklaşımda, sunucu tarafından oluşturulan bir uygulamanın parçaları zaman içinde "başlatılır". Bu, uygulamanın tamamını tek seferde başlatan mevcut yaygın yaklaşımdan farklıdır. Bu sayede, sayfaları etkileşimli hale getirmek için gereken JavaScript miktarını azaltabilirsiniz. Böylece, sayfanın düşük öncelikli bölümlerinin istemci tarafında yükseltilmesini erteleyerek ana iş parçacığını engellemesini önleyebilir ve kullanıcı etkileşimlerinin kullanıcı tarafından başlatıldıktan sonra daha erken gerçekleşmesini sağlayabilirsiniz.

Kademeli yeniden birleştirme, sunucu tarafında oluşturma yeniden birleştirme işleminin en yaygın sorunlarından birini önlemenize de yardımcı olabilir: Sunucu tarafından oluşturulan bir DOM ağacı yok edilir ve hemen ardından yeniden oluşturulur. Bunun nedeni genellikle ilk eşzamanlı istemci tarafı oluşturma işleminin henüz hazır olmayan veriler (genellikle henüz çözümlenmemiş bir Promise) gerektirmesidir.

Kısmi yeniden etkinleştirme

Kısmi rehidrasyonun uygulanmasının zor olduğu görülmüştür. Bu yaklaşım, sayfanın her bir parçasını (bileşenler, görünümler veya ağaçlar) analiz eden ve etkileşimi az olan ya da hiç tepki vermeyen parçaları tanımlayan aşamalı yeniden canlandırmanın bir uzantısıdır. Bu çoğunlukla statik parçaların her biri için ilgili JavaScript kodu, etkisiz referanslara ve dekoratif özelliklere dönüştürülerek istemci tarafındaki ayak izini neredeyse sıfıra indirir.

Kısmi yeniden canlandırma yaklaşımının kendine özgü sorunları ve ödünleri vardır. Önbelleğe alma konusunda bazı ilginç zorluklar ortaya çıkarır ve istemci tarafı gezinme, uygulamanın etkin olmayan bölümleri için sunucu tarafından oluşturulan HTML'nin tam sayfa yükleme olmadan kullanılabileceğini varsayamayacağımız anlamına gelir.

Trisomorfik oluşturma

Hizmet çalışanları sizin için bir seçenekse trisomorfik oluşturmayı düşünün. Bu teknik, ilk veya JavaScript olmayan gezinmeler için akış sunucu tarafı oluşturmayı kullanmanıza ve ardından hizmet çalışanınızın yüklendikten sonra gezinmeler için HTML oluşturma işlemini üstlenmesine 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ğiniz durumlarda en iyi sonucu verir.

Sunucuyla iletişim kuran bir tarayıcı ve hizmet çalışanını gösteren trizomorfik oluşturma.

SEO ile ilgili dikkat edilmesi gereken noktalar

Ekipler, web oluşturma stratejisi seçerken 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çenektir. Tarayıcılar JavaScript'i anlayabilir ancak oluşturma şekilleriyle ilgili genellikle 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 zamanda, mimariniz büyük ölçüde istemci tarafı JavaScript'e bağlıysa dinamik oluşturma da dikkate alınmaya değer bir seçenek haline gelmiştir.

Sonuç

Oluşturma yaklaşımına karar verirken darboğazlarınızın ne olduğunu ölçün ve anlayın. Statik oluşturma veya sunucu tarafı oluşturma yöntemlerinin, hedefinize ulaşmanıza yardımcı olup olmayacağını değerlendirin. Etkileşimli bir deneyim elde etmek için çoğunlukla minimum JavaScript içeren HTML göndermek sorun değildir. Sunucu-istemci spektrumunu gösteren kullanışlı bir infografik:

Oluşturma seçenekleri ve bunların avantajları ile dezavantajları.

Kredi

Yorumları ve ilham verici fikirleri için herkese teşekkür ederiz:

Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson ve Sebastian Markbåge.