Web'de oluşturma

Web geliştiricilerinin alması gereken temel kararlardan biri, uygulamalarında mantık ve oluşturma sürecini nereye uygulayacağıdır. Bu zor bir iş olabilir çünkü web sitesi oluşturmanın çok karmaşık yolları vardır.

Bu alanla ilgili anlayışımızı, son birkaç yılda Chrome'daki büyük sitelerle konuşmamız sayesinde edindik. Genel olarak, geliştiricilerin tam yenileme yaklaşımı yerine sunucu tarafı oluşturmayı veya statik oluşturmayı düşünmelerini öneririz.

Bu kararı verirken seçtiğimiz mimarileri daha iyi anlamak için her bir yaklaşımı sağlam bir şekilde anlamamız ve onlardan bahsederken kullanacağımız tutarlı terminoloji olması gerekir. Oluşturma yaklaşımları arasındaki farklar, web'de oluşturmanın dezavantajlarını sayfa performansı açısından göstermeye yardımcı olur.

Terminoloji

Oluşturma

Sunucu tarafı oluşturma (SSR)
İstemci tarafında çalışan veya evrensel bir uygulamayı sunucuda HTML olarak oluşturma.
İstemci tarafı oluşturma (CSR)
DOM'yi değiştirmek için JavaScript kullanarak uygulama oluşturma.
Sıvı alımı
Sunucu tarafından oluşturulan HTML'nin DOM ağacını ve verilerini yeniden kullanmaları için istemcide JavaScript görünümleri"açılır".
Önceden oluşturma
İstemci taraflı uygulamayı derleme sırasında çalıştırma ve uygulamanın başlangıç durumunu statik HTML olarak yakalama.

Performans

İlk Bayt Zamanı (TTFB)
Bir bağlantının tıklanması ile yeni sayfada yüklenen içeriğin ilk baytı arasındaki süre.
İlk Zengin İçerikli Boyama (FCP)
İstenen içeriğin (makale gövdesi vb.) görünür hale geldiği zaman.
Sonraki boyamayla etkileşim (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 bir INP için proxy metriği.

Sunucu tarafında 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 bunları işleyeceğinden, istemcide veri getirme ve şablon oluşturma için ek gidiş gelişleri önler.

Sunucu tarafı oluşturma genellikle hızlı bir FCP üretir. Sayfa mantığını çalıştırıp sunucuda oluşturmak, istemciye çok fazla JavaScript gönderilmesini önlemenizi sağlar. Bu, sayfa yükleme sırasında ana iş parçacığının aynı sıklıkta engellenmemesi nedeniyle sayfanın TBT'sini azaltmaya yardımcı olur. Bu da daha düşük INP'ye yol açabilir. Ana iş parçacığı daha seyrek engellendiğinde kullanıcı etkileşimlerinin daha kısa sürede gerçekleşme fırsatı olur. Sunucu tarafında oluşturma ile gerçekten sadece kullanıcının tarayıcısına 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ç verir ve akış dokümanı ayrıştırma gibi ilginç tarayıcı optimizasyonları sunar.

FCP ve TTI'yı etkileyen sunucu tarafı oluşturma ve JS yürütme işlemlerini gösteren şema.
Sunucu tarafı oluşturma ile FCP ve TTI.

Sunucu tarafında oluşturma sayesinde kullanıcıların, sitenizi kullanmadan önce CPU'ya bağlı JavaScript'in çalışmasını beklemek zorunda kalmazlar. Üçüncü taraf JS'den kaçınamadığınızda bile kendi birinci taraf JavaScript maliyetlerinizi azaltmak için sunucu tarafı oluşturmayı kullanmak, geri kalan işlemler için daha fazla bütçe elde etmenizi sağlayabilir. Ancak, bu yaklaşımda potansiyel bir denge söz konusudur: 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 olmaması, büyük ölçüde oluşturduğunuz deneyim türüne bağlıdır. Sunucu tarafı oluşturma ile istemci taraflı oluşturmanın doğru uygulamalarının karşılaştırılması konusunda uzun süredir devam eden bir tartışma vardır. Ancak, her zaman bazı sayfalar için değil, bazı sayfalar için sunucu tarafı oluşturmayı kullanmayı tercih edebilirsiniz. Bazı siteler, karma oluşturma tekniklerini başarılı bir şekilde kullanmaktadır. Örneğin, Netflix sunucusu görece statik açılış sayfalarını oluştururken etkileşim yoğun sayfalar için JS'yi önceden getirir ve böylece istemci tarafından oluşturulan daha ağır sayfaların hızlı yüklenme şansını artırır.

Birçok modern çerçeve, kitaplık ve mimari aynı uygulamayı hem istemci hem de sunucuda oluşturmanıza olanak tanır. Sunucu tarafı oluşturma için bu teknikleri kullanabilirsiniz. Bununla birlikte, oluşturma işleminin hem sunucuda hem de istemcide gerçekleştiği mimariler, oldukça farklı performans özellikleri ve ödünleri olan kendi çözüm sınıflarıdır. React kullanıcıları, sunucu DOM API'lerini veya sunucu tarafı oluşturma için Next.js gibi üzerinde oluşturulan çözümleri kullanabilir. Vue kullanıcıları, Vue'nun sunucu tarafı oluşturma rehberini veya Nuxt'ı kullanabilir. Angular, Universal'a sahiptir. Ancak, çoğu popüler çözüm bir tür sıvı alımından yararlandığından, aracınızın kullandığı yaklaşımlara dikkat edin.

Statik oluşturma

Statik oluşturma, derleme zamanında gerçekleşir. Bu yaklaşım, sayfalarınızdaki istemci taraflı JS miktarını sınırlandırdığınız sürece hızlı bir FCP'nin yanı sıra daha düşük TBT ve INP sunar. Sunucu tarafı oluşturma işleminden farklı olarak, bir sayfanın HTML'sinin sunucuda dinamik olarak oluşturulması gerekmez. Bu nedenle, tutarlı şekilde hızlı bir TTFB de elde edilir. Genel olarak 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 işleminden faydalanmak için statik oluşturmaları birden fazla CDN'ye dağıtabilirsiniz.

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

Statik oluşturma çözümleri farklı şekillerde ve boyutlarda olabilir. Gatsby gibi araçlar, geliştiricilere uygulamalarının bir derleme adımı olarak değil, dinamik olarak oluşturulduklarını hissettirmek için tasarlanmıştır. 11ty, Jekyll ve Metalsmith gibi statik site oluşturma araçları statik yapıları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ı gerekmesidir. Bu URL'lerin ne olacağını önceden tahmin edemediğinizde veya çok sayıda benzersiz sayfası olan siteler için bu zor ve 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 gibi özelliklere aşina olabilir. Bununla birlikte, statik oluşturma ve önceden oluşturma farklı davranır: Statik olarak oluşturulan sayfalar, istemci tarafında çok fazla JavaScript yürütmeye gerek kalmadan etkileşimlidir. Önceden oluşturma ise sayfaları gerçekten etkileşimli hale getirmek için istemcide başlatılması gereken Tek Sayfa Uygulaması'nın FCP'sini iyileştirir.

Belirli bir çözümün statik oluşturma mı yoksa önceden oluşturma mı 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 var olmaya devam eder. Ö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 durağandır.

Yararlı bir diğer test de Chrome Geliştirici Araçları'nda ağ kısıtlamayı kullanmak ve bir sayfa etkileşimli hale gelmeden önce ne kadar JavaScript indirildiğine bakmaktır. Önceden işlemenin etkileşimli hale gelmesi için genellikle daha fazla JavaScript gerekir ve bu JavaScript, statik oluşturmada kullanılan progresif geliştirme yaklaşımından daha karmaşık olma eğilimindedir.

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

Sunucu tarafı oluşturma her şey için en iyi çözüm değildir çünkü dinamik yapısı yüksek işlem ek maliyetlerine sahip olabilir. Birçok sunucu tarafı oluşturma çözümü, verileri erken temizlemez, TTFB'yi geciktirmez veya gönderilen verileri iki katına çıkarmaz (örneğin, istemcide JavaScript tarafından kullanılan satır içi durumlar). React'te renderToString(), eşzamanlı ve tek iş parçacıklı olması nedeniyle yavaş olabilir. Newer React sunucusu DOM API'leri, akışı destekler. Bu API, HTML yanıtının ilk kısmını tarayıcıya daha kısa sürede alırken geri kalan kısımlar hâlâ sunucuda oluşturulmaya devam eder.

Sunucu tarafı oluşturma işleminin "doğru" olmasını sağlamak için bileşen önbelleği için bir çözüm bulup geliştirme, bellek tüketimini yönetme, hatırlama tekniklerini kullanma ve diğer meseleler yer alabilir. Genellikle aynı uygulamayı bir kez istemcide ve bir kez sunucuda olmak üzere iki kez işliyor veya yeniden derliyorsunuz. İçeriği daha erken gösteren sunucu tarafı oluşturma işlemi, her zaman yapılacak daha az iş anlamına gelmez. İstemciye sunucu tarafından oluşturulan bir HTML yanıtı alındıktan sonra istemci üzerinde çok fazla çalışmanız varsa bu, web sitenizde yine de daha yüksek TBT ve INP'ye yol açabilir.

Sunucu tarafı oluşturma, her URL için isteğe bağlı HTML üretir, ancak statik olarak oluşturulmuş içerik yayınlamaktan daha yavaş olabilir. Ek işleri yapabilirseniz sunucu tarafı oluşturma ve HTML önbelleğe alma, sunucunun oluşturma süresini önemli ölçüde kısaltabilir. Sunucu tarafı oluşturmanın avantajı, daha fazla "canlı" veri çekme ve statik oluşturmada mümkün olandan daha eksiksiz bir istek kümesine yanıt verebilme yeteneğidir. Kişiselleştirme gerektiren sayfalar, statik oluşturma ile iyi çalışmayan istek türünün somut bir örneğidir.

PWA oluştururken sunucu tarafı oluşturma ilginç kararlar da sağlayabilir: Tam sayfa hizmet çalışanı önbelleğe almayı kullanmak mı yoksa içerikleri sadece sunucuyla oluşturmak mı daha iyidir?

İstemci tarafı oluşturma

İstemci tarafı 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. Etkili sonuç, sunucudan kullanıcının cihazına daha fazla verinin aktarılması ve bunun kendine ait artıları ile birlikte olmasıdır.

İstemci tarafı oluşturma işleminin mobil cihazlarda hızlı yapılması ve bu işlemin hızlandırılması zor olabilir. Kısıtlı bir JavaScript bütçesini tutmak ve mümkün olduğunca az gidiş-dönüş işlemiyle değer teslim etmek için biraz çaba sarf ederek istemci taraflı oluşturmanın, saf sunucu tarafı oluşturma performansını neredeyse taklit edecek şekilde kullanılmasını sağlayabilirsiniz. Kritik komut dosyalarını ve verileri <link rel=preload> ile göndererek ayrıştırıcının sizin için daha hızlı çalışmasını sağlayabilirsiniz. Ayrıca, ilk ve sonraki gezinmelerin hızlı görünmesini sağlamak için PRPL gibi kalıplar kullanmayı da düşünmenizi öneririz.

FCP ve TTI&#39;yı etkileyen istemci taraflı oluşturma işlemini gösteren şema.
İstemci taraflı oluşturma ile FCP ve TTI.

İstemci tarafı oluşturmanın birincil dezavantajı, uygulama büyüdükçe gereken JavaScript miktarının artma eğiliminde olmasıdır. Bu da sayfanın INP'sini etkileyebilir. İşlem gücü için rekabet eden ve sayfanın içeriğinin oluşturulabilmesi için genellikle işlenmesi gereken yeni JavaScript kitaplıklarının, çoklu dolguların ve üçüncü taraf kodun eklenmesiyle bu durum özellikle zorlaşıyor.

İstemci tarafı oluşturmayı 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ölmeyi ve gerektiğinde yalnızca kullanıcının ihtiyaç duyduğu içeriği sunmak için geç yüklenen JavaScript'i kullanmayı düşünmelidir. Etkileşimin az olduğu veya hiç olmadığı deneyimler için sunucu tarafı oluşturma, bu sorunlara daha ölçeklenebilir bir çözüm olabilir.

Tek sayfalık uygulamalar oluşturan kullanıcılar için, çoğu sayfa tarafından paylaşılan kullanıcı arayüzünün temel parçalarını tanımlamak, uygulama kabuğu önbelleğe alma tekniğini uygulamanıza olanak tanır. Sayfa, uygulama kabuğu HTML'sini ve bağımlılıklarını CacheStorage üzerinden çok hızlı bir şekilde yükleyebildiği için bu, Service Worker'larla birlikte tekrarlanan ziyaretlerde algılanan performansı önemli ölçüde iyileştirebilir.

Yeniden kullanılabilir hâle getirme, sunucu tarafı ve istemci taraflı oluşturma işlemlerini birleştirir

Yeniden kullanma, her ikisini de yaparak istemci tarafı ve sunucu tarafı oluşturma arasındaki dengeleri yumuşatmaya çalışan 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. Daha sonra, oluşturma için kullanılan JavaScript ve veriler, oluşturulan dokümana yerleştirilir. Bu işlem dikkatli bir şekilde yapıldığında sunucu tarafı oluşturma gibi hızlı bir FCP elde edilmesini, ardından istemcide tekrar oluşturma yoluyla "alakalı" olmasını sağlar. Bu etkili bir çözüm olsa da performans açısından ciddi dezavantajlar görebilir.

Yeniden kullanılabilir hale getirme ile sunucu tarafı oluşturmanın birincil dezavantajı, FCP'yi iyileştirse bile TBT ve INP üzerinde önemli bir olumsuz etkiye sahip olmasıdır. Sunucu tarafında oluşturulan sayfalar, yüklenmiş ve etkileşimli olarak görünebilir ancak bileşenlerin istemci tarafı komut dosyaları yürütülene ve etkinlik işleyiciler eklenene kadar girişlere gerçekten yanıt veremez. Mobil cihazlarda bu işlem birkaç dakika sürebilir, kullanıcının kafasını karıştırabilir ve canını sıkabilir.

Sulama sorunu: İki ödeyerek bir uygulama

İstemci tarafı JavaScript'in, sunucunun HTML'sini oluşturduğu tüm verileri yeniden istemeden sunucunun kaldığı yerden doğru bir şekilde "başlaması" için çoğu sunucu tarafı oluşturma çözümü, kullanıcı arayüzünün veri bağımlılıklarından gelen yanıtı dokümanda komut dosyası etiketleri olarak seriler. Bu durum çok sayıda HTML'yi kopyaladığı için, su kaybının olması etkileşimin gecikmesinden daha fazla soruna neden olabilir.

Serileştirilmiş kullanıcı arayüzü, satır içi veriler ve Bundle.js komut dosyası içeren HTML dokümanı
HTML dokümanında yinelenen kod.

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 daha sonra istemcide başlatılan kullanıcı arayüzü uygulamasının tam bir kopyasını da döndürür. Kullanıcı arayüzü, bundle.js yüklemeyi ve yürütmeyi bitirene kadar etkileşimli hale gelmez.

Sunucu tarafı oluşturma ve yeniden kullanılabilirleştirme kullanılarak gerçek web sitelerinden toplanan performans metrikleri, bunun nadiren en iyi seçenek olduğunu göstermektedir. Bunun en önemli nedeni, bir sayfanın hazır göründüğü ancak etkileşimli özelliklerinin hiçbirinin çalışmadığı durumlarla ilgili kullanıcı deneyimi üzerindeki etkisidir.

TTI&#39;yı olumsuz etkileyen istemci oluşturmayı gösteren şema.
İstemci taraflı oluşturmanın TTI'ya etkileri.

Yine de, yeniden kullanılabilirleştirme yoluyla sunucu tarafında oluşturmanın umut ışığı var. Kısa vadede, yüksek oranda önbelleğe alınabilir içerikler için sunucu tarafında oluşturmanın kullanılması TTFB'yi azaltarak önceden işlemeye benzer sonuçlar üretebilir. Artımlı, kademeli veya kısmen su sağlamak, bu tekniği gelecekte daha uygulanabilir hale getirmenin anahtarı olabilir.

Sunucu tarafı oluşturma akışı oluşturun ve aşamalı olarak yeniden kullanılabilir hale getirin

Sunucu tarafı oluşturmada son birkaç yılda çeşitli geliştirmeler yapıldı.

Akışlı sunucu tarafı oluşturma, HTML'yi, alındıktan sonra tarayıcının kademeli olarak oluşturabileceği parçalar halinde gönderebilmenizi sağlar. Bu, işaretlemeyi kullanıcılarınıza daha hızlı ulaştırarak FCP'nizin hızlanmasını sağlayabilir. Tepki'de, akışların renderToPipeableStream()'de eşzamansız olması, eşzamanlı renderToString() ile karşılaştırıldığında karşı basıncın iyi yönetildiği anlamına gelir.

Progresif rehidrasyon da dikkate alınması gereken bir noktadır ve React da bunu uyguladı. Bu yaklaşımla birlikte, tüm uygulamayı tek seferde başlatmaya yönelik geçerli yaygın yaklaşım yerine, sunucu tarafından oluşturulan bir uygulamanın ayrı ayrı parçaları zaman içinde "açılır". Bu, sayfaları etkileşimli hale getirmek için gereken JavaScript miktarını azaltmaya yardımcı olabilir. Böylece, ana iş parçacığının engellenmesini önlemek amacıyla sayfanın düşük öncelikli bölümlerinin istemci tarafında yeni sürüme geçirilmesini ertelemenize olanak tanır ve kullanıcı etkileşimlerinin kullanıcı tarafından başlatıldıktan daha erken gerçekleşmesini sağlar.

Progresif yeniden kullanılabilirlik, en yaygın sunucu tarafı oluşturma yeniden kullanılabilirlik risklerinden birini önlemenize de yardımcı olabilir: Sunucu tarafından oluşturulan bir DOM ağacı yok edilir ve hemen yeniden oluşturulur. Bunun nedeni çoğu zaman, başlangıçtaki eş zamanlı istemci tarafında oluşturulan verilerin tam olarak hazır olmaması, genellikle de henüz çözülmemiş bir Promise veri gerektirmesidir.

Kısmi su kaybı

Kısmi rehidrasyonun uygulanması zor görülmüştür. Bu yaklaşım, sayfanın tek tek parçalarını (bileşenler, görünümler veya ağaçlar) analiz eden ve çok az etkileşimi olan ya da hiç tepki vermeyen parçaları belirleyen progresif yeniden sulama sürecinin bir uzantısıdır. Çoğunlukla statik olan bu parçaların her biri için karşılık gelen JavaScript kodu, durağan referanslara ve dekoratif özelliklere dönüştürülerek istemci taraflı ayak izinin neredeyse sıfıra indirilmesini sağlar.

Kısmi sıvı alma yaklaşımının kendine has sorunları ve uzlaşmaları vardır. Önbelleğe alma için bazı ilginç zorluklar içerir ve istemci tarafında gezinme, uygulamanın durağan kısımları için sunucu tarafından oluşturulan HTML'nin tam sayfa yüklenmeden kullanılabilir olduğunu varsayamayacağımız anlamına gelir.

Trisomorfik oluşturma

Service Worker seçenekleri size sunuluyorsa trisomorfik oluşturmayı deneyin. Bu teknik, ilk veya JS olmayan gezinmeler için sunucu tarafında akış oluşturmayı kullanmanıza ve hizmet çalışanınızın yüklendikten sonra gezinme için HTML oluşturmayı üstlenmesine olanak tanıyan bir tekniktir. Bu, önbelleğe alınan bileşenleri ve şablonları güncel tutabilir ve aynı oturumda yeni görünümler oluşturmak için SPA stili gezinmelerin yapılmasını sağlayabilir. Bu yaklaşım aynı şablon ve yönlendirme kodunu sunucu, istemci sayfası ve hizmet çalışanı arasında paylaşabildiğinizde en iyi sonucu verir.

Sunucuyla iletişim kuran bir tarayıcı ve Service Worker&#39;ı gösteren Trisomorfik oluşturma şeması.
Tizomorfik oluşturmanın işleyiş şeklini gösteren bir şema.

SEO ile ilgili dikkat edilmesi gereken noktalar

Ekipler, web oluşturma stratejisi belirlerken genellikle SEO'nun etkisini göz önünde bulundurur. Sunucu tarafı oluşturma, tarayıcıların yorumlayabileceği "eksiksiz" bir deneyim sunmak için popüler bir seçenektir. Tarayıcılar JavaScript'i anlayabilir, ancak genellikle bunların oluşturulma şekliyle ilgili kısıtlamalar söz konusudur. İstemci tarafı oluşturma çalışabilir, ancak genellikle ek teste ve ek yüke ihtiyaç duyar. Daha yakın zamanda, mimariniz büyük ölçüde istemci taraflı JavaScript'e bağlıysa dinamik oluşturma da değerlendirilmeye değer bir seçenek haline geldi.

Mobil uyumluluk testi aracından emin olmadığınızda, seçtiğiniz yaklaşımın beklediğiniz sonuçları verip vermediğini test etmenin harika bir yoludur. Bu rapor, herhangi bir sayfanın Google'ın tarayıcısına nasıl göründüğünü, JavaScript yürütüldükten sonra bulduğu serileştirilmiş HTML içeriğini ve oluşturma sırasında karşılaşılan hataların görsel bir önizlemesini gösterir.

Mobil Uyumluluk Testi kullanıcı arayüzünün ekran görüntüsü.
Mobil Uyumluluk Testi Kullanıcı Arayüzü.

Sonuç

Oluşturma yaklaşımına karar verirken performans sorunlarını ölçün ve anlayın. Statik oluşturmanın mı yoksa sunucu tarafı oluşturmanın mı size en iyi şekilde yol gösterebileceğini düşünün. Etkileşimli bir deneyim elde etmek için çoğunlukla HTML'yi minimum JavaScript ile göndermeniz sorun yaratmaz. Sunucu-istemci spektrumunu gösteren faydalı bir infografike göz atın:

Bu makalede açıklanan seçenek yelpazesini gösteren infografik.
Oluşturma seçenekleri ve artıları.

Kredi

İncelemeleri ve ilham verdikleri için herkese teşekkür ederiz:

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