Uygulama Kabuğu Mimarisi ile Web Uygulamalarını Anında Yükleme

Addy Osmani
Addy Osmani
Matt Gaunt

Uygulama kabuğu, kullanıcı arayüzünü çalıştıran basit HTML, CSS ve JavaScript kodlarıdır. Uygulama kabuğu:

  • hızlı yükle
  • önbelleğe alınmış olmalıdır
  • içeriği dinamik olarak görüntüleme

Güvenilir ve iyi performansın sırrı, uygulama kabuğundadır. Uygulamanızın kabuğunu, yerel bir uygulama geliştirirken uygulama mağazasında yayınlayacağınız kod paketi gibi düşünün. Bu, işe başlamak için gereken yük olsa da hikayenin tamamı olmayabilir. Kullanıcı arayüzünü yerel düzeyde tutar ve API yoluyla içeriği dinamik olarak çeker.

HTML, JS ve CSS kabuğu ile HTML içeriğinin uygulama kabuğunun ayrılması

Arka plan

Alex Russell'ın Progresif Web Uygulamaları (Progresif Web Uygulamaları) makalesinde, çevrimdışı destek, push bildirimleri ve ana ekrana ekleme özelliği ile daha yerel uygulamaya benzer bir deneyim sunmak için web uygulamalarının kullanım ve kullanıcı rızası yoluyla nasıl aşamalı olarak değişebileceği açıklanmaktadır. Büyük ölçüde Service Worker'ın işlevi ve performans avantajları ile önbelleğe alma becerilerine bağlıdır. Bu, hıza odaklanmanıza olanak tanır ve web uygulamalarınıza yerel uygulamalarda görmeye alışkın olduğunuz anında yüklenme özelliğini ve düzenli güncellemeleri sağlar.

Bu özelliklerden tam olarak yararlanmak için web siteleriyle ilgili yeni bir düşünme şekline ihtiyacımız var: uygulama kabuğu mimarisi.

Service Worker artırılmış uygulama kabuğu mimarisi kullanarak uygulamanızı nasıl yapılandıracağınızı inceleyelim. Hem istemci hem de sunucu tarafında oluşturmaya göz atacağız ve bugün deneyebileceğiniz uçtan uca bir örnek paylaşacağız.

Önemli noktayı vurgulamak için aşağıdaki örnekte, bu mimariyi kullanan bir uygulamanın ilk yüklemesi gösterilmektedir. Ekranın en altında "Uygulama çevrimdışı kullanıma hazır" mesajının göründüğüne dikkat edin. Daha sonra kabuk için bir güncelleme kullanıma sunulursa kullanıcıyı yeni sürüm için yenileme yapması konusunda bilgilendirebiliriz.

Uygulama kabuğu için Geliştirici Araçları'nda çalışan hizmet çalışanının resmi

Service Worker nedir?

Service Worker, web sayfanızdan ayrı olarak arka planda çalışan bir komut dosyasıdır. Hizmet verdiği sayfalardan yapılan ağ istekleri ve sunucunuzdan gelen push bildirimleri de dahil olmak üzere etkinliklere yanıt verir. Bir hizmet çalışanının ömrü kasıtlı olarak kısadır. Bir etkinlik aldığında uyanır ve yalnızca işlemesi gereken süre boyunca çalışır.

Normal tarama bağlamındaki JavaScript'e kıyasla Service Worker'ların sınırlı sayıda API'si vardır. Bu, web'de çalışanlar için standarttır. Bir Service çalışanı DOM'ye erişemez ancak Cache API gibi öğelere erişebilir ve Fetch API'yi kullanarak ağ isteklerinde bulunabilir. IndexedDB API ve postMessage(), hizmet çalışanı ile kontrol ettiği sayfalar arasında veri kalıcılığı ve mesajlaşma için de kullanılabilir. Sunucunuzdan gönderilen push etkinlikleri, kullanıcı etkileşimini artırmak için Bildirim API'sini çağırabilir.

Bir hizmet çalışanı, bir sayfadan yapılan ağ isteklerine müdahale edebilir (hizmet çalışanında bir getirme etkinliğini tetikler) ve ağdan alınan, yerel bir önbellekten alınan ve hatta programatik olarak oluşturulan bir yanıt döndürebilir. Etkin bir şekilde, tarayıcıda programlanabilir bir proxy'dir. İşin güzel tarafı, yanıtın nereden geldiğine bakılmaksızın web sayfasına sanki hizmet çalışanı dahil değilmiş gibi görünür.

Service Worker'lar hakkında ayrıntılı bilgi için Hizmet Çalışanlarına Giriş başlıklı makaleyi okuyun.

Performans avantajları

Service Worker'lar çevrimdışı önbelleğe alma için güçlüdür ancak aynı zamanda sitenize veya web uygulamanıza yapılan yinelenen ziyaretler için anında yükleme şeklinde önemli performans kazanımları sunar. Çevrimdışı çalışması için uygulama kabuğunuzu önbelleğe alabilir ve JavaScript kullanarak içeriğini doldurabilirsiniz.

Tekrarlanan ziyaretlerde bu, içeriğiniz sonunda ağdan gelse bile, ekranda ağ olmadan anlamlı pikseller almanıza olanak tanır. Bunu, araç çubuklarını ve kartları hemen görüntüleyip, ardından içeriğinizin geri kalanını aşamalı olarak yüklemek gibi düşünebilirsiniz.

Bu mimariyi gerçek cihazlarda test etmek için WebPageTest.org adresinde uygulama kabuğu örneğimizi çalıştırdık ve aşağıdaki sonuçları gördük.

1. Test: Chrome Dev'i kullanarak Nexus 5 ile Kablo üzerinde test etme

Uygulamanın ilk görünümünün, tüm kaynakları ağdan getirmesi gerekir ve 1,2 saniye içinde anlamlı bir boyama sağlayamaz. Service Worker önbelleğe alma özelliği sayesinde, tekrar eden ziyaretimiz anlamlı bir renklendirme sağlar ve yükleme işlemini 0,5 saniyede tamamen tamamlar.

Kablo Bağlantısı için Web Sayfası Test Boyama Diyagramı

2. Test: Chrome Dev'i kullanarak Nexus 5 ile 3G'de test etme

Örneğimizi, biraz daha yavaş bir 3G bağlantısıyla da test edebiliriz. Bu kez, ilk anlamlı boyamızın ilk ziyarette tamamlanması 2,5 saniye sürüyor. Sayfanın tamamen yüklenmesi 7,1 saniye sürer. Service Worker önbelleğe alma özelliği sayesinde, tekrar eden ziyaretimiz anlamlı boyamalar gerçekleştirir ve yüklemeyi 0,8 saniye içinde tamamen tamamlar.

3G Bağlantısı İçin Web Sayfası Test Boyama Diyagramı

Diğer görünümler de benzer bir hikaye anlatır. Uygulama kabuğunda ilk anlamlı boyamanın elde edilmesi için gereken 3 saniyeyi karşılaştırın:

Web Sayfası Testi'nden ilk görünüm için zaman çizelgesini boya

Service Worker önbelleğinden aynı sayfa yüklendiğinde geçen 0,9 saniyeye kadar. Son kullanıcılarımız için 2 saniyeden fazla zaman kazanılır.

Web Sayfası Testi'nden tekrar eden görünüm için zaman çizelgesini boya

Uygulama kabuğu mimarisini kullanan kendi uygulamalarınız için de benzer ve güvenilir performans kazançları elde edebilirsiniz.

Service Worker için uygulamaları yapılandırma biçimimizi yeniden düşünmemiz gerekiyor mu?

Service Worker'lar, uygulama mimarisinde bazı ince değişiklikler yapar. Uygulamanızın tamamını bir HTML dizesine sığdırmak yerine AJAX stili işlemler yapabilirsiniz. Bu, her zaman önbelleğe alınan ve ağ olmadan her zaman başlatılabilen bir kabuğunuzun ve düzenli olarak yenilenip ayrı olarak yönetilen içeriğinizin olduğu yerdir.

Bu bölünmenin etkisi büyüktür. İlk ziyaretinizde, sunucuda içerik oluşturabilir ve Service Worker'ı istemciye yükleyebilirsiniz. Sonraki ziyaretlerde yalnızca veri isteğinde bulunmanız yeterlidir.

Progresif geliştirme nedir?

Service Worker şu anda tüm tarayıcılar tarafından desteklenmemekle birlikte, uygulama içeriği kabuk mimarisi, herkesin içeriğe erişebilmesi için progresif geliştirme özelliğini kullanır. Mesela örnek projemizi ele alalım.

Aşağıda Chrome, Firefox Gecelik ve Safari'de oluşturulan tam sürümü görebilirsiniz. En solda, içeriğin bir hizmet çalışanı olmadan sunucuda oluşturulduğu Safari sürümünü görebilirsiniz. Sağda, Service Worker tarafından desteklenen Chrome ve Firefox Nightly sürümlerini görüyoruz.

Safari, Chrome ve Firefox'ta yüklenen Uygulama Kabuğunun görüntüsü

Bu mimariyi ne zaman kullanmak mantıklıdır?

Uygulama kabuğu mimarisi, dinamik uygulamalar ve siteler için en mantıklı olandır. Siteniz küçük ve statikse muhtemelen uygulama kabuğuna ihtiyacınız yoktur ve hizmet çalışanı oninstall adımında tüm siteyi önbelleğe almanız yeterlidir. Projeniz için en mantıklı yaklaşımı kullanın. Bazı JavaScript çerçeveleri, uygulama mantığınızı içerikten ayırmayı teşvik etmektedir ve bu da bu kalıbın uygulanması daha kolay hale gelir.

Henüz bu kalıbı kullanan üretim uygulamaları var mı?

Uygulama kabuğu mimarisi, genel olarak uygulamanızın kullanıcı arayüzünde yapılan birkaç değişiklikle mümkün hale gelmiştir. Google'ın I/O 2015 Progresif Web Uygulaması ve Google'ın gelen kutusu gibi büyük ölçekli sitelerde sorunsuz şekilde çalışmaktadır.

Google Gelen Kutusu'nun yüklendiği resmi. Service Worker'ı kullanarak Gelen Kutusu'nu gösteriyor.

Performans açısından büyük bir kazanım elde eden çevrimdışı uygulama kabukları, Jake Archibald'ın çevrimdışı Wikipedia uygulaması ve Flipkart Lite’ın progresif web uygulamasında da iyi şekilde kanıtlandı.

Jake Archibald'ın Wikipedia Demo ekran görüntüleri.

Mimariyi açıklama

İlk yükleme deneyiminde hedefiniz, anlamlı içeriği kullanıcının ekranına mümkün olduğunca hızlı bir şekilde göstermektir.

İlk olarak diğer sayfaları yükleme

Uygulama Kabuğu ile İlk Yükleme şeması

Genel olarak uygulama kabuğu mimarisi:

  • İlk yüklemeye öncelik verin ancak hizmet çalışanın, uygulama kabuğunu önbelleğe almasına izin verin. Böylece tekrarlanan ziyaretlerde, kabuğun ağdan yeniden getirilmesi gerekmez.

  • Diğer her şeyi geç yükleme veya arka planda yükleme. İyi bir seçenek, dinamik içerik için okunabilir önbelleğe alma özelliğini kullanmaktır.

  • Statik içeriğinizi yöneten hizmet çalışanını güvenilir bir şekilde önbelleğe almak ve güncellemek için sw-precache gibi Service Worker araçlarından yararlanın. (Sw-precache hakkında daha sonra daha fazla bilgi edineceksiniz.)

Bunu başarmak için:

  • Sunucu, istemcinin oluşturabileceği HTML içeriğini gönderir ve hizmet çalışanı desteği olmayan tarayıcıları hesaba katmak için ilerideki HTTP önbellek geçerlilik sonu başlıklarını kullanır. Uygulama yaşam döngüsünün ilerleyen aşamalarında hem 'sürüm oluşturmayı' hem de kolay güncellemeleri mümkün kılmak için karmalardan yararlanarak dosya adları sunar.

  • Sayfalar, uygulama kabuğunun ilk hızlı boyamasını sağlamak için <head> dokümanındaki bir <style> etiketine satır içi CSS stilleri ekler. Her sayfa, mevcut görünüm için gerekli olan JavaScript'i eşzamansız olarak yükler. CSS eşzamansız olarak yüklenemediğinden, ayrıştırıcı odaklı ve eşzamanlı değil, eşzamansız olduğu için JavaScript kullanarak stilleri isteyebiliriz. Hızlı bir önbellek isabeti sağlayabilecek ve stillerin yanlışlıkla kritik oluşturma yolunun bir parçası haline geleceği durumları önlemek için requestAnimationFrame() özelliğinden de yararlanabiliriz. requestAnimationFrame(), stiller yüklenmeden önce ilk karenin boyanmasını zorlar. Diğer bir seçenek, JavaScript kullanarak CSS'yi eşzamansız olarak istemek için Filament Grubu'nun loadCSS gibi projeleri kullanmaktır.

  • Service Worker, uygulama kabuğunun önbelleğe alınmış bir girişini saklar. Böylece, tekrar eden ziyaretlerde ağda bir güncelleme yoksa kabuk, tamamen hizmet çalışanı önbelleğinden yüklenebilir.

İçerik İçin Uygulama Kabuğu

Pratik uygulama

Uygulama kabuğu mimarisi, istemci için eski ES2015 JavaScript ve sunucu için Express.js kullanarak tümüyle çalışan bir örnek hazırladık. Elbette istemci veya sunucu bölümleri (ör.PHP, Ruby, Python) için kendi yığınınızı kullanmanızı engelleyen bir şey yoktur.

Hizmet çalışanı yaşam döngüsü

Uygulama kabuğu projemizde, aşağıdaki hizmet çalışanı yaşam döngüsünü sunan sw-precache kullanıyoruz:

Etkinlik İşlem
Yükle Uygulama kabuğunu ve diğer tek sayfalık uygulama kaynaklarını önbelleğe alın.
Etkinleştir Eski önbellekleri temizleyin.
Getirme URL'ler için tek sayfalık web uygulaması yayınlayın ve öğeler ile önceden tanımlanmış parçalar için önbelleği kullanın. Diğer istekler için ağı kullanın.

Sunucu bit değerleri

Bu mimaride, bir sunucu tarafı bileşeni (bu örnekte, Express'te yazılmıştır) içeriği ve sunumu ayrı ayrı işleyebilmelidir. İçerik, sayfanın statik olarak oluşturulmasıyla sonuçlanan bir HTML düzenine eklenebilir ya da ayrı olarak sunulup dinamik olarak yüklenebilir.

Tahmin edebileceğiniz gibi, sunucu tarafı kurulumunuz demo uygulamamız için kullandığımızdan büyük ölçüde farklı olabilir. Web uygulamalarındaki bu kalıbı çoğu sunucu kurulumu gerçekleştirebilir ancak bazı yeniden mimari oluşturma gerekir. Aşağıdaki modelin oldukça iyi çalıştığını tespit ettik:

Uygulama Kabuğu Mimarisi şeması
  • Uç noktalar, uygulamanızın üç bölümü için tanımlanır: kullanıcıya bakan URL'ler (dizin/joker karakter), uygulama kabuğu (hizmet çalışanı) ve sizin HTML parçalarınız.

  • Her uç noktanın, tuvalet çubuğu düzenini çeken bir denetleyici vardır. Bu da gidon kısmı kısımlarını ve görünümlerini alabilir. Basitçe ifade etmek gerekirse kısmi görüntülemeler, son sayfaya kopyalanan HTML parçaları olan görünümlerdir. Not: Daha gelişmiş veri senkronizasyonu yapan JavaScript çerçevelerinin Uygulama Kabuğu mimarisine taşınması genellikle çok daha kolaydır. Kısmi işlemler yerine veri bağlama ve senkronizasyon kullanma eğilimindedirler.

  • Kullanıcıya başlangıçta içeriği olan statik bir sayfa sunulur. Bu sayfada, destekleniyorsa uygulama kabuğunu ve bağlı olduğu her şeyi (CSS, JS vb.) önbelleğe alan bir hizmet çalışanı kaydedilir.

  • Böylece uygulama kabuğu, belirli bir URL'nin içeriğinde XHR için JavaScript'i kullanarak tek sayfalık bir web uygulaması gibi çalışır. XHR çağrıları, ilgili içeriği görüntülemek için gereken küçük HTML, CSS ve JS parçasını döndüren bir /partials* uç noktasına yapılır. Not: Buna yaklaşmanın birçok yolu vardır ve XHR, bunlardan yalnızca biridir. Bazı uygulamalar ilk oluşturma için verilerini satır içine alır (belki JSON kullanır) ve bu nedenle, birleştirilmiş HTML anlamında "statik" olmaz.

  • Service Worker desteği olmayan tarayıcılara her zaman yedek deneyim sunulmalıdır. Demomuzda temel sunucu tarafı oluşturmaya geri döneriz ancak bu, birçok seçenekten yalnızca biridir. Hizmet çalışanı özelliği, önbelleğe alınmış uygulama kabuğunu kullanarak tek sayfalık uygulama stili uygulamanızın performansını artırmak için yeni fırsatlar sunar.

Dosya sürümü oluşturma

Akıllara takılan sorulardan biri de dosya sürümü oluşturma ve güncelleme işlemlerinin nasıl yapılacağıdır. Bu, uygulamaya özgüdür ve seçenekler şunlardır:

  • Ağ'ı seçin, aksi takdirde önbelleğe alınan sürümü kullanın.

  • Yalnızca ağ. Çevrimdışıysa başarısız olur.

  • Eski sürümü önbelleğe alıp daha sonra güncelleyin.

Uygulama kabuğunun kendisi için hizmet çalışanı kurulumunuz için önbellek öncelikli bir yaklaşım uygulanmalıdır. Uygulama kabuğunu önbelleğe alamıyorsanız mimariyi doğru şekilde benimsememişsiniz demektir.

Alet

Uygulamanızın kabuğunu önceden önbelleğe alma veya yaygın önbelleğe alma kalıplarını yönetme sürecini kolaylaştıran, kurulum işlemini kolaylaştıran çok sayıda farklı Service Worker yardımcı kitaplığı sunuyoruz.

Web Fundamentals&#39;taki Service Worker Library sitesinin ekran görüntüsü

Uygulama kabuğunuz için sw-precache kullanma

Uygulama kabuğunu önbelleğe almak için sw-precache kullanmak; dosya düzeltmeleri, yükleme/etkinleştirme soruları ve uygulama kabuğunun getirme senaryosu ile ilgili sorunları ele almalıdır. sw-precache'yi uygulamanızın derleme işlemine bırakın ve statik kaynaklarınızı almak için yapılandırılabilir joker karakterler kullanın. Service Worker komut dosyanızı manuel olarak oluşturmak yerine sw-precache'nin önbellek öncelikli getirme işleyicisi kullanarak önbelleğinizi güvenli ve verimli bir şekilde yöneten bir komut dosyası oluşturmasına izin verin.

Uygulamanıza yapılan ilk ziyaretler, gerekli kaynakların tamamının önceden önbelleğe alınmasını tetikler. Bu, uygulama mağazasından yerel uygulama yükleme deneyimine benzer. Kullanıcılar uygulamanıza geri döndüğünde yalnızca güncellenen kaynaklar indirilir. Demomuzda, "Uygulama güncellemeleri Yeni sürüm için sayfayı yenileyin." Bu kalıp, kullanıcılara en son sürüm için yenileme yapabileceklerini bildirmenin kolay bir yoludur.

Çalışma zamanı önbelleğe alma için sw-toolbox kullanma

Kaynağa bağlı olarak değişen stratejilerle çalışma zamanı önbelleğe alma işlemi için sw-toolbox aracını kullanın:

  • Resimler için cacheFirst ve özel son geçerlilik tarihi N maxEntries politikasına sahip, özel bir adlandırılmış önbellek.

  • İstenen içeriğin güncelliğine bağlı olarak networkFirst veya API istekleri için en hızlısı. En hızlı seçenek olabilir ancak sık sık güncellenen belirli bir API feed'i varsa networkFirst'ü kullanın.

Sonuç

Uygulama kabuğu mimarileri çeşitli avantajlar sunar ancak yalnızca bazı uygulama sınıfları için anlamlıdır. Model henüz yeni olduğundan bu mimarinin sağlayacağı çaba ve genel performans avantajlarını değerlendirmek faydalı olacaktır.

Deneysel çalışmalarımızda, iki uygulama katmanı oluşturma işini en aza indirmek için istemci ile sunucu arasında şablon paylaşımından yararlandık. Bu, progresif geliştirmenin hâlâ temel bir özellik olmasını sağlar.

Uygulamanızda zaten Service Worker kullanmayı düşünüyorsanız mimariye göz atın ve kendi projeleriniz için uygun olup olmadığını değerlendirin.

Yorumcularımız sayesinde: Jeff Posnick, Paul Lewis, Alex Russell, Seth Thompson, Rob Dodson, Taylor Savage ve Joe Medley.