Netlify ve Next.js ile Hacimli Yapıları Yıkmak

Yayınlanan: 2022-03-10
Kısa özet ↬ Statik Üretim, performans için harikadır - uygulama çok büyüyene ve yapım süreleri çatıdan geçene kadar. Bugün, Netlify'ın yeni İsteğe Bağlı Oluşturucularının bunu nasıl düzeltebileceğine bir göz atacağız. Ek olarak, en iyi kullanıcı ve geliştirici deneyimi için Next.js'nin Artımlı Statik Yenileme ile eşleştiriyoruz. Ve elbette, bu sonuçları kıyaslayın!

Statik olarak oluşturulmuş web siteleriyle çalışmanın en büyük sıkıntılarından biri, uygulamanız büyüdükçe yapıların giderek daha yavaş olmasıdır. Bu, herhangi bir yığının bir noktada karşılaştığı kaçınılmaz bir sorundur ve ne tür bir ürünle çalıştığınıza bağlı olarak farklı noktalardan vurabilir.

Örneğin, uygulamanızın dağıtım yapıtını oluştururken birden çok sayfası (görünümler, yollar) varsa, bu yolların her biri bir dosya haline gelir. Ardından, binlerce kişiye ulaştığınızda, önceden plan yapmanıza gerek kalmadan ne zaman konuşlandırabileceğinizi merak etmeye başlarsınız. Bu senaryo, zaten web'in büyük bir bölümünü oluşturan ancak tamamı olmayan e-ticaret platformlarında veya bloglarda yaygındır. Yine de, olası tek darboğaz rotalar değildir.

Kaynak ağırlıklı bir uygulama da sonunda bu dönüm noktasına ulaşacaktır. Birçok statik oluşturucu, en iyi kullanıcı deneyimini sağlamak için varlık optimizasyonu gerçekleştirir. Derleme optimizasyonları olmadan (artımlı derlemeler, önbelleğe alma, yakında bunlara ulaşacağız) bu da sonunda yönetilemez hale gelecektir - bir web sitesindeki tüm resimleri gözden geçirmeyi düşünün: yeniden boyutlandırma, silme ve/veya tekrar tekrar yeni dosyalar oluşturma. Ve tüm bunlar bittiğinde: Jamstack'in uygulamalarımızı İçerik Dağıtım Ağı'nın kenarlarından sunduğunu unutmayın. Bu yüzden hala bir şeyleri derlendikleri sunucudan ağın kenarlarına taşımamız gerekiyor.

Jamstack genel hizmet mimarisi
Jamstack genel hizmet mimarisi (Geniş önizleme)

Tüm bunlara ek olarak, başka bir gerçek daha var: veriler genellikle dinamiktir, yani uygulamamızı oluşturup dağıttığımızda birkaç saniye, birkaç dakika ve hatta bir saat sürebilir. Bu arada dünya dönmeye devam ediyor ve başka bir yerden veri alıyorsak, uygulamamızın modası geçeceği kesin. Kabul edilemez! Güncellemek için tekrar oluşturun!

Bir Kez Oluşturun, Gerektiğinde Güncelleyin

Hacimli Yapıları Çözmek, bir süredir temel olarak her Jamstack platformu, çerçevesi veya hizmeti için akılda tutulmuştur. Birçok çözüm, artımlı yapılar etrafında döner. Pratikte bu, yapıların mevcut dağıtıma göre taşıdıkları farklılıklar kadar hacimli olacağı anlamına gelir.

Yine de bir fark algoritması tanımlamak kolay bir iş değildir. Son kullanıcının bu iyileştirmeden gerçekten yararlanabilmesi için dikkate alınması gereken önbellek geçersiz kılma stratejileri vardır. Uzun lafın kısası: Bir sayfa veya değişmemiş bir varlık için önbelleği geçersiz kılmak istemiyoruz.

Next.js, Artımlı Statik Yenileme ( ISR ) ile geldi. Özünde, her rota için ne sıklıkta yeniden inşa edilmesini istediğimizi bildirmenin bir yoludur. Kaputun altında, sunucu tarafındaki birçok işi basitleştirir. Çünkü her rota (dinamik ya da değil) belirli bir zaman çerçevesi içinde kendini yeniden oluşturacaktır ve Jamstack'in her derlemede önbelleği geçersiz kılma aksiyomuna mükemmel bir şekilde uyar. Bunu max-age başlığı olarak düşünün, ancak Next.js uygulamanızdaki rotalar için.

Uygulamanızı başlatmak için ISR yalnızca bir yapılandırma özelliği uzağınızda. Rota bileşeninizde ( /pages dizininin içinde) getStaticProps yönteminize gidin ve revalidate anahtarını dönüş nesnesine ekleyin:

 export async function getStaticProps() { const { limit, count, pokemons } = await fetchPokemonList() return { props: { limit, count, pokemons, }, revalidate: 3600 // seconds } }

Yukarıdaki snippet, sayfamın her saat yeniden oluşturulmasını ve görüntülenecek daha fazla Pokemon getirmesini sağlayacaktır.

Hala ara sıra toplu yapıları alıyoruz (yeni bir dağıtım yayınlarken). Ancak bu, içeriği bir İçerik Yönetim Sistemine (CMS) taşıyarak içeriği koddan ayırmamızı sağlar, uygulamamız ne kadar büyük olursa olsun bilgileri birkaç saniye içinde güncelleyebiliriz. Yazım hatalarını güncellemek için web kancalarına elveda!

İsteğe Bağlı Oluşturucular

Netlify kısa süre önce Next.js için ISR'yi destekleme yaklaşımı olan İsteğe Bağlı Oluşturucuları başlattı, ancak aynı zamanda Eleventy ve Nuxt dahil olmak üzere çerçeveler arasında da çalışıyor. Önceki oturumda, ISR'nin daha kısa yapım süreleri için büyük bir adım olduğunu belirledik ve kullanım durumlarının önemli bir bölümünü ele aldık. Yine de, uyarılar vardı:

  1. Sürekli dağıtım üzerine tam sürümler.
    Artımlı aşama, yalnızca dağıtımdan sonra ve veriler için gerçekleşir. Kodu aşamalı olarak göndermek mümkün değil
  2. Artımlı yapılar zamanın bir ürünüdür.
    Önbellek zaman bazında geçersiz kılınır. Bu nedenle, kodda ayarlanan yeniden doğrulama süresine bağlı olarak gereksiz derlemeler meydana gelebilir veya gerekli güncellemeler daha uzun sürebilir.

Netlify'ın yeni dağıtım altyapısı, geliştiricilerin, uygulamalarının hangi parçalarının dağıtım üzerine oluşturulacağını ve hangi parçaların erteleneceğini (ve bunların nasıl erteleneceğini) belirlemek için mantık oluşturmasına olanak tanır.

  • kritik
    Herhangi bir işlem gerekli değildir. Dağıttığınız her şey push üzerine inşa edilecektir.
  • Ertelenmiş
    Uygulamanın belirli bir parçası dağıtım üzerine oluşturulmayacak, ilk istek gerçekleştiğinde istek üzerine oluşturulması ertelenecek, daha sonra türünün herhangi bir kaynağı olarak önbelleğe alınacaktır.

İsteğe Bağlı oluşturucu oluşturma

Her şeyden önce, projenize bir netlify/functions paketini devDependency olarak ekleyin:

 yarn add -D @netlify/functions

Bu yapıldığında, yeni bir Netlify İşlevi oluşturmakla aynıdır. Onlar için belirli bir dizin belirlemediyseniz, netlify/functions/ ve oluşturucunuz için herhangi bir adla bir dosya oluşturun.

 import type { Handler } from '@netlify/functions' import { builder } from '@netlify/functions' const myHandler: Handler = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Built on-demand! ' }), } } export const handler = builder(myHandler)

Yukarıdaki parçadan görebileceğiniz gibi, isteğe bağlı oluşturucu, işleyicisini bir builder() yönteminin içine sardığı için normal bir Netlify İşlevinden ayrılır. Bu yöntem, işlevimizi derleme görevlerine bağlar. Başvurunuzun bir kısmının yalnızca gerektiğinde inşa için ertelenmesi için ihtiyacınız olan tek şey budur. Hareket halindeyken küçük artımlı yapılar!

Netlify'da Next.js

Netlify'da bir Next.js uygulaması oluşturmak için, genel olarak daha iyi bir deneyime sahip olmak için eklenmesi gereken 2 önemli eklenti vardır: Netlify Plugin Cache Next.js ve Essential Next-on-Netlify. İlki, NextJS'nizi daha verimli bir şekilde önbelleğe alır ve onu kendiniz eklemeniz gerekirken, ikincisi, Netlify'ın mimarisine daha iyi uyması ve varsayılan olarak Netlify'ın tanımlayabileceği her yeni projede kullanılabilir olması için Next.js mimarisinin nasıl oluşturulduğuna ilişkin birkaç küçük ayarlama yapar. Next.js kullanarak.

Next.js ile İsteğe Bağlı Oluşturucular

Performans oluşturma, dağıtım performansı, önbelleğe alma, geliştirici deneyimi. Bunların hepsi çok önemli konulardır, ancak çoktur ve düzgün bir şekilde kurulması zaman alır. Ardından, Kullanıcı Deneyimi yerine Geliştirici Deneyimine odaklanma konusundaki o eski tartışmaya geliyoruz. Bu, işlerin unutulmak için bir biriktirme listesindeki gizli bir noktaya gittiği zamandır. Pek sayılmaz.

Netlify arkanızda. Sadece birkaç adımda Next.js uygulamamızda Jamstack'in tüm gücünden yararlanabiliriz. Şimdi kolları sıvama ve hepsini bir araya getirme zamanı.

Önceden Oluşturulmuş Yolları Tanımlama

Daha önce Next.js içinde statik oluşturma ile çalıştıysanız, muhtemelen getStaticPaths yöntemini duymuşsunuzdur. Bu yöntem, dinamik rotalar (çok çeşitli sayfaları oluşturacak sayfa şablonları) için tasarlanmıştır. Bu yöntemin incelikleri üzerinde çok fazla durmadan, dönüş türünün 2 anahtarlı bir nesne olduğunu not etmek önemlidir, Kavram Kanıtımızdaki gibi bu [Pokemon] dinamik rota dosyası olacaktır:

 export async function getStaticPaths() { return { paths: [], fallback: 'blocking', } }
  • paths , önceden oluşturulacak olan bu rotayla eşleşen tüm yolları yürüten bir array .
  • fallback 3 olası değeri vardır: engelleme, true veya false

Bizim durumumuzda getStaticPaths belirler:

  1. Hiçbir yol önceden oluşturulmaz;
  2. Bu rota her çağrıldığında, bir geri dönüş şablonu sunmayacağız, sayfayı istek üzerine oluşturacağız ve uygulamanın başka bir şey yapmasını engelleyerek kullanıcıyı bekleteceğiz.

İsteğe Bağlı Oluşturucuları kullanırken, yedek stratejinizin uygulamanızın hedeflerini karşıladığından emin olun, resmi Next.js belgeleri: yedek belgeler çok faydalıdır.

İsteğe Bağlı Oluşturuculardan önce getStaticPaths biraz farklıydı:

 export async function getStaticPaths() { const { pokemons } = await fetchPkmList() return { paths: pokemons.map(({ name }) => ({ params: { pokemon: name } })), fallback: false, } }

Sahip olmayı düşündüğümüz tüm pokemon sayfalarının bir listesini topluyorduk, tüm pokemon nesnelerini sadece pokemon adıyla bir string eşliyor ve onu taşıyan { params } nesnesini getStaticProps . Geri dönüşümüz false olarak ayarlandı, çünkü bir rota eşleşmediyse fallback bir 404: Not Found sayfası atmasını istedik.

Netlify'a dağıtılan her iki sürümü de kontrol edebilirsiniz:

  • İsteğe Bağlı Oluşturucu ile: kod, canlı
  • Tamamen statik oluşturulmuş: kod, canlı

Kod ayrıca Github'da açık kaynaklıdır ve oluşturma sürelerini kontrol etmek için kendiniz kolayca dağıtabilirsiniz. Ve bu sıra ile bir sonraki konumuza geçiyoruz.

İnşa Süreleri

Yukarıda bahsedildiği gibi, önceki demo aslında bir Proof-of-Concept , ölçemezsek hiçbir şey gerçekten iyi veya kötü değildir. Küçük çalışmamız için PokeAPI'ye gittim ve tüm pokemonları yakalamaya karar verdim.

Tekrarlanabilirlik amacıyla, isteğimizi sınırladım ( 1000 ). Bunların hepsi API içinde değil, ancak herhangi bir zamanda herhangi bir zamanda güncellenip güncellenmediğine bakılmaksızın, tüm yapılar için sayfa sayısının aynı olmasını zorunlu kılar.

 export const fetchPkmList = async () => { const resp = await fetch(`${API}pokemon?limit=${LIMIT}`) const { count, results, }: { count: number results: { name: string url: string }[] } = await resp.json() return { count, pokemons: results, limit: LIMIT, } }

Ardından, temelde aynı ortamda bir arada bulunabilecekleri önizleme dağıtımları sayesinde, her iki sürümü de ayrı dallarda Netlify'a ateşledi. Her iki yöntem arasındaki farkı gerçekten değerlendirmek için ODB yaklaşımı aşırıydı, bu dinamik rota için hiçbir sayfa önceden oluşturulmamıştı. Gerçek dünya senaryoları için önerilmese de (trafiğin yoğun olduğu rotalarınızı önceden oluşturmak isteyeceksiniz), bu yaklaşımla elde edebileceğimiz yapım süresi performans iyileştirme aralığını açıkça gösterir.

strateji Sayfa sayısı Varlık Sayısı Yapım Zamanı Toplam dağıtım süresi
Tamamen Statik Oluşturuldu 1002 1005 2 dakika 32 saniye 4 dakika 15 saniye
İsteğe Bağlı Oluşturucular 2 0 52 saniye 52 saniye

Küçük PokeDex uygulamamızdaki sayfalar oldukça küçüktür, görüntü varlıkları çok yalındır, ancak dağıtım süresindeki kazanımlar çok önemlidir. Bir uygulamanın orta ila büyük miktarda rotası varsa, kesinlikle ODB stratejisini dikkate almaya değer.

Dağıtımlarınızı daha hızlı ve dolayısıyla daha güvenilir hale getirir. Performans artışı yalnızca ilk istekte gerçekleşir, sonraki istekten sonra oluşturulan sayfa doğrudan Edge'de önbelleğe alınır ve performansı Tam Statik Oluşturulan ile tamamen aynı hale getirir.

Gelecek: Dağıtılmış Kalıcı İşleme

Aynı gün, İsteğe Bağlı Oluşturucular duyuruldu ve erken erişime açıldı, Netlify ayrıca Dağıtılmış Kalıcı İşleme (DPR) hakkında Yorum İsteği'ni yayınladı.

DPR, İsteğe Bağlı Oluşturucular için bir sonraki adımdır. Bu tür asenkron oluşturma adımlarını kullanarak ve ardından varlıkları gerçekten güncellenene kadar önbelleğe alarak daha hızlı derlemelerden yararlanır. 10 bin sayfalık bir web sitesi için artık tam sürümler yok. DPR, geliştiricilere, katı önbelleğe alma ve İsteğe Bağlı Oluşturucuları kullanarak sistemleri oluşturma ve dağıtma konusunda tam denetim yetkisi verir.

Şu senaryoyu hayal edin: Bir e-ticaret web sitesinde 10 bin ürün sayfası var, bu da uygulamanın tamamının dağıtım için oluşturulmasının yaklaşık 2 saat alacağı anlamına geliyor. Bunun ne kadar acı verici olduğunu tartışmamıza gerek yok.

DPR ile ilk 500 sayfayı her dağıtımda oluşturulacak şekilde ayarlayabiliriz. En yoğun trafik sayfalarımız, kullanıcılarımız için her zaman hazırdır. Ama biz bir dükkanız yani her saniyenin önemi var. Bu nedenle, diğer 9500 sayfa için, oluşturucularını tetiklemek için bir derleme sonrası kanca ayarlayabiliriz - kalan sayfalarımızı eşzamansız olarak dağıtır ve hemen önbelleğe alırız. Hiçbir kullanıcı zarar görmedi, web sitemiz mümkün olan en hızlı derlemeyle güncellendi ve önbellekte olmayan her şey saklandı.

Çözüm

Bu makaledeki tartışma noktalarının çoğu kavramsal olmasına ve uygulamanın tanımlanması gerekmesine rağmen, Jamstack'in geleceği konusunda heyecanlıyım. Topluluk olarak yaptığımız ilerlemeler, son kullanıcı deneyimi etrafında dönüyor.

Dağıtılmış Kalıcı İşleme konusundaki yaklaşımınız nedir? Uygulamanızda İsteğe Bağlı Oluşturucuları denediniz mi? Yorumlarda bana daha fazla bilgi verin veya beni Twitter'da arayın. Ben gerçekten merak ediyorum!

Referanslar

  • “Next.js ile Artımlı Statik Yenileme (ISR) İçin Eksiksiz Bir Kılavuz,” Lee Robinson
  • “Talep Üzerine Oluşturucularla Netlify Üzerindeki Büyük Siteler İçin Daha Hızlı Yapılar,” Asavari Tayal, Netlify Blog
  • “Dağıtılmış Kalıcı İşleme: Daha Hızlı Derlemeler İçin Yeni Bir Jamstack Yaklaşımı,” Matt Biilmann, Netlify Blog
  • "Dağıtılmış Kalıcı İşleme (DPR)," Cassidy Williams, GitHub