Uygulama kabuğu, kullanıcı arayüzünü destekleyen minimum HTML, CSS ve JavaScript'dir. Uygulama kabuğu:
- hızlı yükleme
- önbelleğe alınır.
- İçeriği dinamik olarak görüntüleme
Uygulama kabuğu, güvenilir bir şekilde iyi performans elde etmenin sırrıdır. Uygulamanızın kabuğunu, yerel bir uygulama geliştiriyorsanız uygulama mağazasında yayınlayacağınız kod paketi gibi düşünebilirsiniz. Bu, uygulamanızın ilk kez yayınlanması için gereken yüktür ancak uygulamanızın tamamı bu kadar olmayabilir. Kullanıcı arayüzünüzü yerel tutar ve içeriği API aracılığıyla dinamik olarak alır.
Arka plan
Alex Russell'ın Progresif Web Uygulamaları makalesinde, bir web uygulamasının kullanım ve kullanıcı izniyle nasıl kademeli olarak değişerek çevrimdışı destek, push bildirimleri ve ana ekrana eklenme özelliğiyle birlikte daha yerel uygulama benzeri bir deneyim sunabileceği açıklanmaktadır. Bu, hizmet çalışanının işlevselliğine ve performans avantajlarına, ayrıca önbelleğe alma özelliklerine bağlıdır. Bu sayede hıza odaklanabilirsiniz. Böylece web uygulamalarınıza, yerel uygulamalarda görmeye alıştığınız anında yükleme ve düzenli güncelleme özelliklerini sunabilirsiniz.
Bu özelliklerden tam olarak yararlanmak için web siteleri hakkında yeni bir düşünme şekline ihtiyacımız var: uygulama kabuğu mimarisi.
Uygulamanızı hizmet çalışanı destekli uygulama kabuğu mimarisi kullanarak nasıl yapılandıracağınızı inceleyelim. Hem istemci hem de sunucu taraflı oluşturmaya bakacağız ve bugün deneyebilirsiniz uçtan uca bir örnek paylaşacağız.
Bu noktayı vurgulamak için aşağıdaki örnekte, bu mimariyi kullanan bir uygulamanın ilk yüklenmesi gösterilmektedir. Ekranın alt kısmındaki "Uygulama çevrimdışı kullanıma hazır" bildirimini görebilirsiniz. Kabukta daha sonra bir güncelleme yayınlanırsa kullanıcıyı yeni sürüme geçmesi için bilgilendirebiliriz.
Hizmet çalışanları nedir?
Hizmet çalışanı, web sayfanızdan ayrı olarak arka planda çalışan bir komut dosyasıdır. Sunulan sayfalardan yapılan ağ istekleri ve sunucunuzdan gelen push bildirimleri dahil olmak üzere etkinliklere yanıt verir. Hizmet çalışanlarının kullanım ömrü kasıtlı olarak kısadır. Bir etkinlik aldığında uyanır ve yalnızca etkinliği işlemesi gerektiği sürece çalışır.
Hizmet çalışanları, normal bir tarama bağlamındaki JavaScript'e kıyasla sınırlı bir API grubuna da sahiptir. Bu, web'deki işçiler için standarttır. Hizmet çalışanları DOM'a erişemez ancak Cache API gibi öğelere erişebilir ve Fetch API'yi kullanarak ağ istekleri gönderebilir. IndexedDB API ve postMessage(), hizmet çalışanı ile kontrol ettiği sayfalar arasında veri koruma ve mesajlaşma için de kullanılabilir. Sunucunuzdan gönderilen push etkinlikleri, kullanıcı etkileşimini artırmak için Notification API'yi çağırabilir.
Hizmet çalışanları, bir sayfadan yapılan ağ isteklerini (hizmet çalışanında bir getirme etkinliği tetikler) durdurabilir ve ağdan veya yerel bir önbellekten alınan ya da programlı olarak oluşturulan bir yanıt döndürebilir. Aslında tarayıcıda programlanabilir bir proxy'dir. Güzel olan şey, yanıtın nereden geldiğine bakılmaksızın web sayfası için hizmet çalışanının dahil olmadığı bir durum gibi görünmesidir.
Hizmet çalışanları hakkında daha ayrıntılı bilgi edinmek için Hizmet Çalışanlarına Giriş başlıklı makaleyi okuyun.
Performans avantajları
Hizmet çalışanları, çevrimdışı önbelleğe alma için güçlüdür ancak sitenize veya web uygulamanıza yapılan tekrar ziyaretlerde anında yükleme şeklinde önemli performans kazanımları da sunar. Uygulama kabuğunuzu çevrimdışı çalışacak şekilde önbelleğe alabilir ve içeriğini JavaScript kullanarak doldurabilirsiniz.
Bu sayede, tekrarlanan ziyaretlerde içeriğiniz ağdan gelse bile ağ olmadan ekranda anlamlı pikseller elde edebilirsiniz. Araç çubuklarını ve kartları hemen, içeriğinizin geri kalanını ise kademeli olarak yüklemeyi düşünün.
Bu mimariyi gerçek cihazlarda test etmek için uygulama kabuğu örneğimizi WebPageTest.org'da çalıştırdık ve sonuçları aşağıda gösterdik.
1. Test: Chrome Dev'i kullanarak Nexus 5 ile kablolu test
Uygulamanın ilk görüntüsünde tüm kaynakların ağdan getirilmesi gerekir ve 1,2 saniye geçene kadar anlamlı bir boyama işlemi gerçekleştirilmez. Hizmet çalışanı önbelleğe alma özelliği sayesinde, tekrar ziyaretimiz anlamlı bir boya elde eder ve yükleme işlemi 0,5 saniye içinde tamamen tamamlanır.
2. Test: Chrome Dev'i kullanan Nexus 5 ile 3G'de test etme
Örneğimizi biraz daha yavaş bir 3G bağlantısıyla da test edebiliriz. Bu sefer, ilk anlamlı boyamamız için ilk ziyarette 2,5 saniye sürüyor. Sayfanın tamamen yüklenmesi 7,1 saniye sürüyor. Hizmet çalışanı önbelleğe alma özelliği sayesinde, tekrar ziyaretimiz anlamlı bir boya elde eder ve yükleme işlemi 0,8 saniye içinde tamamen tamamlanır.
Diğer görünümler de benzer bir tabloyu gösteriyor. Uygulama kabuğunda ilk anlamlı boyamaya ulaşmak için gereken 3 saniye ile karşılaştırın:
0,9 saniye olan aynı sayfanın hizmet çalışanı önbelleğimizden yüklenmesi işlemine kıyasla. Son kullanıcılarımız 2 saniyeden fazla zaman kazanıyor.
Uygulama kabuğu mimarisini kullanan kendi uygulamalarınızda da benzer ve güvenilir performans kazanımları elde edebilirsiniz.
Hizmet çalışanı, uygulamaları nasıl yapılandırdığımızı yeniden düşünmemizi gerektiriyor mu?
Hizmet çalışanları, uygulama mimarisinde bazı küçük değişiklikler anlamına gelir. Uygulamanızın tamamını bir HTML dizesine sıkıştırmak yerine işlemleri AJAX tarzında yapmak yararlı olabilir. Burada bir kabuk (her zaman önbelleğe alınır ve ağ olmadan her zaman başlatılabilir) ve düzenli olarak yenilenen ve ayrı olarak yönetilen içerik bulunur.
Bu bölünmenin etkileri büyüktür. İlk ziyarette, sunucudaki içeriği oluşturabilir ve hizmet çalışanını istemciye yükleyebilirsiniz. Sonraki ziyaretlerde yalnızca verileri istemeniz gerekir.
Peki progresif geliştirme?
Hizmet çalışanı şu anda tüm tarayıcılar tarafından desteklenmese de uygulama içeriği kabuğu mimarisi, herkesin içeriğe erişebilmesini sağlamak için aşamalı geliştirme kullanır. Örneğin, örnek projemizi ele alalım.
Aşağıda, Chrome, Firefox Nightly ve Safari'de oluşturulan tam sürümü görebilirsiniz. En solda, içeriğin sunucu üzerinde bir hizmet çalışanı olmadan oluşturulduğu Safari sürümünü görebilirsiniz. Sağ tarafta, hizmet çalışanı tarafından desteklenen Chrome ve Firefox Nightly sürümlerini görüyoruz.
Bu mimariyi ne zaman kullanmak mantıklı olur?
Uygulama kabuğu mimarisi, dinamik uygulamalar ve siteler için en uygun seçenektir. Siteniz küçük ve statikse muhtemelen bir uygulama kabuğuna ihtiyacınız yoktur ve sitenin tamamını bir hizmet çalışanı oninstall
adımında önbelleğe alabilirsiniz. Projeniz için en uygun yaklaşımı kullanın. Bazı JavaScript çerçeveleri, uygulama mantığınızı içerikten ayırmanızı zaten teşvik ediyor. Bu da bu kalıbın uygulanmasını daha kolay hale getiriyor.
Bu kalıbı kullanan üretim aşamasındaki uygulamalar var mı?
Uygulama kabuğu mimarisi, genel uygulamanızın kullanıcı arayüzünde yalnızca birkaç değişiklikle kullanılabilir ve Google'ın I/O 2015 Progressive Web Uygulaması ve Google'ın Gelen Kutusu gibi büyük ölçekli sitelerde iyi sonuç vermiştir.
Çevrimdışı uygulama kabukları, performans açısından önemli bir avantajdır ve Jake Archibald'ın çevrimdışı Wikipedia uygulamasında ve Flipkart Lite'ın progresif web uygulamasında da iyi bir şekilde gösterilmiştir.
Mimarisi hakkında açıklama
İlk yükleme deneyimi sırasında amacınız, anlamlı içeriği kullanıcının ekranına mümkün olduğunca hızlı bir şekilde sunmaktır.
İlk yükleme ve diğer sayfaların yüklenmesi
Genel olarak uygulama kabuğu mimarisi:
İlk yüklemeye öncelik verin ancak hizmet çalışanını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 yavaş yükleyin veya arka planda yükleyin. Dinamik içerikler için okuma önbelleğe alma özelliğini kullanmak iyi bir seçenektir.
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 hizmet çalışanı araçlarını kullanın. (sw-precache hakkında daha fazla bilgiyi aşağıda bulabilirsiniz.)
Bunu yapmak için:
Sunucu, istemcinin oluşturabileceği HTML içeriği gönderir ve hizmet çalışanı desteği olmayan tarayıcıları hesaba katmak için çok uzak gelecekteki HTTP önbellek geçerlilik bitiş tarihi üst bilgilerini kullanır. Hem "sürüm oluşturmayı" hem de uygulama yaşam döngüsünün sonraki aşamalarında kolay güncellemeler yapılmasını sağlamak için dosya adlarını karma oluşturma işlemleriyle sunar.
Sayfalar, uygulama kabuğunun hızlı bir şekilde ilk boyanmasını sağlamak için
<head>
belgesindeki bir<style>
etiketinde satır içi CSS stilleri içerir. Her sayfa, geçerli görünüm için gerekli JavaScript'i eşzamansız olarak yükler. CSS eşzamansız olarak yüklenemediğinden, ayrıştırıcı destekli ve senkronize yerine eşzamansız olduğu için JavaScript kullanarak stiller isteğinde bulunabiliriz. Hızlı bir önbellek isabeti alabileceğimiz ve stillerin yanlışlıkla kritik oluşturma yolunun bir parçası haline gelebileceği durumları önlemek içinrequestAnimationFrame()
özelliğinden de yararlanabiliriz.requestAnimationFrame()
, stillerin yüklenmesinden önce ilk karenin boyanmasını zorlar. Başka bir seçenek de JavaScript kullanarak CSS'yi eşzamansız olarak istemek için Filament Group'un loadCSS gibi projeleri kullanmaktır.Hizmet çalışanı, uygulama kabuğunun önbelleğe alınmış bir girişini depolar. Böylece, ağda güncelleme olmadığı sürece kabuk, tekrarlanan ziyaretlerde tamamen hizmet çalışanı önbelleğinden yüklenebilir.
Pratik bir uygulama
Uygulama kabuğu mimarisini, istemci için standart ES2015 JavaScript'i ve sunucu için Express.js'i kullanarak tamamen çalışan bir örnek yazdık. İstemci veya sunucu bölümleri için kendi paketinizi (ör.PHP, Ruby, Python) kullanmanızı engelleyen hiç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'i kullanırız:
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. |
Getir | URL'ler için tek sayfalık bir web uygulaması sunun ve önbelleği öğeler ve önceden tanımlanmış kısmi içerikler için kullanın. Diğer istekler için ağı kullanın. |
Sunucu bitleri
Bu mimaride, sunucu tarafı bir bileşen (bizim durumumuzda Express'te yazılmış) içeriği ve sunumu ayrı ayrı işleyebilmelidir. İçerik, sayfanın statik olarak oluşturulmasına yol açan bir HTML düzenine eklenebilir veya ayrı olarak sunulup dinamik olarak yüklenebilir.
Sunucu tarafı kurulumunuzun, demo uygulamamız için kullandığımızdan çok farklı olabileceği anlaşılabilir. Bu web uygulaması kalıbı çoğu sunucu kurulumunda kullanılabilir ancak bazı yeniden mimari çalışmaları gerektirir. Aşağıdaki modelin oldukça iyi sonuç verdiğini tespit ettik:
Bitiş noktaları, uygulamanızın üç bölümü için tanımlanır: kullanıcılara yönelik URL'ler (dizin/joker karakter), uygulama kabuğu (hizmet çalışanı) ve HTML kısmi öğeleriniz.
Her uç noktada, kontrol çubuğu düzenini alan bir denetleyici bulunur. Bu düzen de kontrol çubuğu kısmi öğelerini ve görünümlerini alabilir. Basitçe açıklamak gerekirse, kısmi görünümler, son sayfaya kopyalanan HTML parçalarıdır. Not: Daha gelişmiş veri senkronizasyonu yapan JavaScript çerçevelerinin bir uygulama kabuğu mimarisine taşınması genellikle çok daha kolaydır. Kısmi veriler yerine veri bağlama ve senkronizasyon kullanma eğilimindedirler.
Kullanıcıya başlangıçta içerik barındıran statik bir sayfa sunulur. Bu sayfa, destekleniyorsa uygulama kabuğunu ve bağlı olduğu her şeyi (CSS, JS vb.) önbelleğe alan bir hizmet çalışanı kaydeder.
Ardından uygulama kabuğu, belirli bir URL'nin içeriğinde XHR yapmak için JavaScript kullanarak tek sayfalı bir web uygulaması gibi davranır. XHR çağrıları, bu 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: Bu konuya yaklaşımın birçok yolu vardır ve XHR bunlardan yalnızca biridir. Bazı uygulamalar, ilk oluşturma işlemi için verilerini satır içi olarak (JSON kullanarak olabilir) yerleştirir ve bu nedenle düzleştirilmiş HTML anlamında "statik" değildir.
Hizmet çalışanı desteği olmayan tarayıcılara her zaman yedek deneyim sunulmalıdır. Demomuzda, temel statik sunucu tarafı oluşturmaya geri dönüyoruz 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 stilindeki uygulamanızın performansını artırmanıza yönelik yeni fırsatlar sunar.
Dosya sürümü oluşturma
Burada ortaya çıkan sorulardan biri, dosya sürümlendirme ve güncelleme işlemlerinin nasıl yapılacağıdır. Bu, uygulamaya özeldir ve seçenekler şunlardır:
Önce ağ, aksi takdirde önbelleğe alınmış sürümü kullanın.
Yalnızca ağ bağlantısı üzerinden çalışır ve ç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ı kurulumunuzda önbelleğe öncelikli yaklaşım uygulanmalıdır. Uygulama kabuğunu önbelleğe almıyorsanız mimariyi doğru şekilde benimsememişsiniz demektir.
Araç
Uygulamanızın kabuğunu önceden önbelleğe alma veya yaygın önbelleğe alma kalıplarını yönetme sürecini daha kolay ayarlamanızı sağlayan çeşitli hizmet çalışanı yardımcı kitaplıklarımız vardır.
Uygulama kabuğunuz için sw-precache'i kullanma
Uygulama kabuğunu önbelleğe almak için sw-precache'i kullanmak, dosya düzeltmeleriyle, yükleme/etkinleştirme sorularıyla ve uygulama kabuğunun getirme senaryosuyla ilgili endişeleri gidermelidir. sw-precache'i uygulamanızın derleme sürecine ekleyin ve statik kaynaklarınızı almak için yapılandırılabilir joker karakterler kullanın. Hizmet çalışanı komut dosyanızı manuel olarak oluşturmak yerine, önbelleğe öncelikli getirme işleyicisi kullanarak önbelleğinizi güvenli ve verimli bir şekilde yöneten bir komut dosyası oluşturması için sw-precache'i kullanın.
Uygulamanıza yapılan ilk ziyaretler, gerekli tüm kaynakları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, yeni bir kabuk kullanıma sunulduğunda kullanıcıları "Uygulama güncellemeleri" mesajıyla bilgilendiriyoruz. Yeni sürüm için yenileyin." Bu kalıp, kullanıcılara en son sürümü güncelleyebileceklerini kolayca bildirmenin 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ında önbelleğe alma için sw-toolbox'ı kullanın:
Resimler için cacheFirst ve N maxEntries özel bir son kullanma politikasına sahip özel bir adlandırılmış önbellek.
İstenen içerik güncelliğine bağlı olarak API istekleri için networkFirst veya en hızlı. En hızlı seçeneği kullanabilirsiniz ancak sık güncellenen belirli bir API feed'i varsa networkFirst seçeneğini kullanın.
Sonuç
Uygulama kabuğu mimarileri birçok avantaj sunsa da yalnızca bazı uygulama sınıfları için anlamlıdır. Model henüz yeni olduğundan bu mimarinin çaba ve genel performans avantajlarını değerlendirmeye değer.
Denemelerimizde, iki uygulama katmanı oluşturma işini en aza indirmek için istemci ile sunucu arasında şablon paylaşımından yararlandık. Bu sayede, aşamalı geliştirmenin temel bir özellik olarak kalmasını sağlarız.
Uygulamanızda hizmet çalışanlarını kullanmayı düşünüyorsanız mimariye göz atın ve kendi projeleriniz için uygun olup olmadığını değerlendirin.
Yorumcularımız Jeff Posnick, Paul Lewis, Alex Russell, Seth Thompson, Rob Dodson, Taylor Savage ve Joe Medley'e teşekkür ederiz.