Bu, Google Bulletin ekibinin dışa dönük bir PWA oluştururken öğrendiği derslerle ilgili bir dizi blog gönderisinin ilkidir. Bu gönderilerde, karşılaştığımız bazı zorlukları, bunların üstesinden gelmek için uyguladığımız yaklaşımları ve tuzaklardan kaçınmak için genel tavsiyeleri paylaşacağız. Bu, hiçbir şekilde PWA’ların tam bir özeti değildir. Amaç, ekibimizin deneyimlerinden öğrenilenleri paylaşmaktır.
Bu ilk gönderi için önce biraz arka plan bilgisine değineceğiz ve ardından servis çalışanları hakkında öğrendiğimiz her şeyi derinlemesine inceleyeceğiz.
Arka plan #
Bülten, 2017 ortasından 2019 ortasına kadar aktif olarak geliştiriliyordu.
Neden bir PWA oluşturmayı seçtik? #
Geliştirme sürecine girmeden önce, bir PWA oluşturmanın bu proje için neden cazip bir seçenek olduğunu inceleyelim:
- Hızlı yineleme yeteneği. Bulletin birden çok pazarda deneneceği için özellikle değerli.
- Tek kod tabanı. Kullanıcılarımız, Android ve iOS arasında kabaca eşit bir şekilde bölünmüştü. Bir PWA, her iki platformda da çalışacak tek bir web uygulaması oluşturabileceğimiz anlamına geliyordu. Bu, takımın hızını ve etkisini artırdı.
- Hızlı ve kullanıcı davranışından bağımsız olarak güncellenir. PWA’lar otomatik olarak güncellenebilir ve bu da vahşi ortamdaki güncel olmayan istemcilerin miktarını azaltır. Müşteriler için çok kısa bir geçiş süresiyle arka uç değişikliklerinin üstesinden gelmeyi başardık.
- Birinci ve üçüncü taraf uygulamalarla kolayca entegre edin. Bu tür entegrasyonlar, uygulama için bir gereklilikti. Bir PWA ile bu genellikle basitçe bir URL açmak anlamına geliyordu.
- Bir uygulama yükleme sürtünmesi kaldırıldı.
çerçevemiz #
Bülten için kullandığımız Polimerancak herhangi bir modern, iyi desteklenmiş çerçeve çalışacaktır.
Hizmet çalışanları hakkında öğrendiklerimiz #
olmadan bir PWA’ya sahip olamazsınız. hizmet çalışanı. Hizmet çalışanları size gelişmiş önbelleğe alma stratejileri, çevrimdışı yetenekler, arka plan senkronizasyonu vb. gibi çok fazla güç sağlar. Hizmet çalışanları biraz karmaşıklık eklese de, faydalarının eklenen karmaşıklıktan daha ağır bastığını gördük.
yapabilirsen üret #
El ile bir hizmet çalışanı komut dosyası yazmaktan kaçının. Hizmet çalışanlarını el ile yazmak, önbelleğe alınmış kaynakları el ile yönetmeyi ve çoğu hizmet çalışanı kitaplığında ortak olan yeniden yazma mantığını gerektirir; çalışma kutusu.
Bununla birlikte, dahili teknoloji yığınımız nedeniyle hizmet çalışanımızı oluşturmak ve yönetmek için bir kitaplık kullanamadık. Aşağıda öğrendiklerimiz zaman zaman bunu yansıtacaktır. git Oluşturulmamış hizmet çalışanları için tuzaklar daha fazla okumak için
Tüm kitaplıklar hizmet çalışanı uyumlu değildir #
Bazı JS kitaplıkları, bir hizmet çalışanı tarafından çalıştırıldığında beklendiği gibi çalışmayan varsayımlarda bulunur. Örneğin, varsayarak window
veya document
kullanılabilir veya hizmet çalışanları tarafından kullanılamayan bir API kullanıyor (XMLHttpRequest
, yerel depolama vb.). Uygulamanız için ihtiyaç duyduğunuz tüm kritik kitaplıkların servis çalışanı ile uyumlu olduğundan emin olun. Bu özel PWA için kullanmak istedik boşluk.js kimlik doğrulama için, ancak hizmet çalışanlarını desteklemediği için yapamadılar. Kitaplık yazarları ayrıca, hizmet çalışanı ile uyumsuz API’lerden kaçınmak gibi hizmet çalışanı kullanım durumlarını desteklemek için mümkün olduğunda JavaScript bağlamı hakkındaki gereksiz varsayımları azaltmalı veya kaldırmalıdır. küresel devletten kaçınmak.
Başlatma sırasında IndexedDB’ye erişmekten kaçının #
okuma IndexedDB hizmet çalışanı betiğinizi başlatırken, aksi halde bu istenmeyen duruma girebilirsiniz:
- Kullanıcı, IndexedDB (IDB) N sürümüne sahip bir web uygulamasına sahip
- Yeni web uygulaması, IDB sürüm N+1 ile gönderilir
- Kullanıcı, yeni hizmet çalışanının indirilmesini tetikleyen PWA’yı ziyaret eder
- Yeni hizmet çalışanı kaydolmadan önce IDB’den okur
install
N’den N+1’e gitmek için bir IDB yükseltme döngüsünü tetikleyen olay işleyicisi - Kullanıcı, N sürümüne sahip eski bir istemciye sahip olduğundan, etkin bağlantılar veritabanının eski sürümüne açık olduğundan hizmet çalışanı yükseltme işlemi askıda kalıyor
- Hizmet çalışanı askıda kalıyor ve asla yükleme yapmıyor
Bizim durumumuzda, önbellek hizmet çalışanı yüklemesinde geçersiz kılındı, bu nedenle hizmet çalışanı hiç yüklenmediyse, kullanıcılar güncellenen uygulamayı asla almadı.
Esnek yap #
Hizmet çalışanı betikleri arka planda çalışsa da, herhangi bir zamanda, G/Ç işlemlerinin (ağ, IDB, vb.) ortasındayken bile sonlandırılabilirler. Uzun süren herhangi bir süreç, herhangi bir noktada devam ettirilebilir olmalıdır.
Büyük dosyaların sunucuya yüklendiği ve IDB’ye kaydedildiği bir senkronizasyon işlemi söz konusu olduğunda, kesintiye uğrayan kısmi yüklemeler için çözümümüz, dahili yükleme kitaplığımızın devam ettirilebilir sisteminden yararlanmak, devam ettirilebilir yükleme URL’sini yüklemeden önce IDB’ye kaydetmek ve ilk seferinde tamamlanmayan bir yüklemeyi sürdürmek için bu URL’yi kullanmaktı. Ayrıca herhangi bir uzun süreli G/Ç işleminden önce, her kayıt için sürecin neresinde olduğumuzu belirtmek üzere durum IDB’ye kaydedildi.
Küresel devlete bağlı kalmayın #
Servis çalışanları farklı bir bağlamda var olduğundan, var olmasını bekleyebileceğiniz pek çok sembol mevcut değildir. Kodumuzun çoğu her ikisinde de çalıştı window
bağlamın yanı sıra bir hizmet çalışanı bağlamı (günlüğe kaydetme, bayraklar, eşitleme vb.). Kodun, yerel depolama veya tanımlama bilgileri gibi kullandığı hizmetler konusunda savunmacı olması gerekir. Kullanabilirsiniz globalThis
tüm bağlamlarda çalışacak şekilde küresel nesneye atıfta bulunmak. Komut dosyasının ne zaman sonlandırılacağına ve durumun ne zaman tahliye edileceğine dair bir garanti olmadığından, genel değişkenlerde saklanan verileri idareli kullanın.
Yerel kalkınma #
Hizmet çalışanlarının önemli bir bileşeni, kaynakları yerel olarak önbelleğe almaktır. Ancak, geliştirme sırasında bu kesin zıt özellikle güncellemeler tembel yapıldığında. Bununla ilgili sorunları ayıklayabilmek veya arka plan senkronizasyonu veya bildirimler gibi diğer API’lerle çalışabilmek için yine de sunucu çalışanının yüklenmesini istiyorsunuz. Chrome’da bunu etkinleştirerek Chrome DevTools aracılığıyla elde edebilirsiniz. Ağ için baypas onay kutusu (Başvuru paneli > servis çalışanları bölmesi) etkinleştirmenin yanı sıra önbelleği devre dışı bırak onay kutusu Ağ önbelleği de devre dışı bırakmak için panel. Daha fazla tarayıcıyı kapsamak için, geliştirici yapılarında varsayılan olarak etkin olan hizmet çalışanımıza önbelleğe almayı devre dışı bırakan bir işaret ekleyerek farklı bir çözüm seçtik. Bu, geliştiricilerin her zaman en son değişikliklerini herhangi bir önbelleğe alma sorunu olmadan almasını sağlar. dahil etmek önemlidir. Cache-Control: no-cache
tarayıcının herhangi bir varlığı önbelleğe almasını önlemek için başlık.
deniz feneri #
deniz feneri PWA’lar için faydalı bir dizi hata ayıklama aracı sağlar. Bir siteyi tarar ve PWA’ları, performansı, erişilebilirliği, SEO’yu ve diğer en iyi uygulamaları kapsayan raporlar oluşturur. Öneririz Lighthouse’u sürekli entegrasyon üzerinde çalıştırma PWA olma kriterlerinden birini çiğnerseniz sizi uyarmak için. Bu aslında bir kez başımıza geldi, servis çalışanı yükleme yapmıyordu ve biz bunu üretime geçmeden önce fark etmemiştik. Deniz Feneri’nin CI’mizin bir parçası olması bunu engelleyebilirdi.
Sürekli teslimatı benimseyin #
Hizmet çalışanları otomatik olarak güncelleme yapabildiğinden, kullanıcılar yükseltmeleri sınırlama olanağından yoksundur. Bu, vahşi ortamdaki güncel olmayan istemcilerin miktarını önemli ölçüde azaltır. Kullanıcı uygulamamızı açtığında, hizmet çalışanı yeni istemciyi yavaş yavaş indirirken eski istemciye hizmet verirdi. Yeni istemci indirildikten sonra, kullanıcıdan yeni özelliklere erişmek için sayfayı yenilemesini ister. Kullanıcı bu isteği görmezden gelse bile, sayfayı bir sonraki yenilemelerinde istemcinin yeni sürümünü alacaklardı. Sonuç olarak, bir kullanıcının iOS/Android uygulamalarında olduğu gibi güncellemeleri reddetmesi oldukça zordur.
Müşteriler için çok kısa bir geçiş süresiyle arka uç değişikliklerinin üstesinden gelmeyi başardık. Genellikle, kullanıcılara önemli değişiklikler yapmadan önce daha yeni istemcilere güncelleme yapmaları için bir ay süre veririz. Uygulama eskiyken hizmet vereceğinden, kullanıcı uygulamayı uzun süre açmamışsa eski istemcilerin vahşi ortamda var olması aslında mümkündü. iOS’ta hizmet çalışanları birkaç hafta sonra tahliye yani bu olay olmaz. Android için bu sorun, eski durumdayken sunulmayarak veya içeriğin kullanım süresi birkaç hafta sonra manuel olarak sona erdirilerek azaltılabilir. Uygulamada, eski müşterilerden kaynaklanan sorunlarla hiç karşılaşmadık. Belirli bir ekibin burada ne kadar katı olmak istediği, kendi özel kullanım durumlarına bağlıdır, ancak PWA’lar, iOS/Android uygulamalarından önemli ölçüde daha fazla esneklik sağlar.
Bir hizmet çalışanında çerez değerleri alma #
Bazen bir hizmet çalışanı bağlamında çerez değerlerine erişmek gerekir. Bizim durumumuzda, birinci taraf API isteklerini doğrulamak için bir belirteç oluşturmak üzere çerez değerlerine erişmemiz gerekiyordu. Bir hizmet çalışanında, aşağıdakiler gibi senkronize API’ler document.cookies
mevcut değil. Çerez değerlerini istemek için hizmet çalışanından etkin (pencereli) istemcilere her zaman bir mesaj gönderebilirsiniz, ancak hizmet çalışanının herhangi bir pencereli istemci olmadan, örneğin bir arka plan senkronizasyonu sırasında arka planda çalışması mümkündür. Bu soruna geçici bir çözüm bulmak için, ön uç sunucumuzda tanımlama bilgisi değerini istemciye geri yansıtan bir uç nokta oluşturduk. Hizmet çalışanı bu uç noktaya bir ağ isteği yaptı ve çerez değerlerini almak için yanıtı okudu.
piyasaya sürülmesiyle Çerez Mağazası API’sıtarayıcı tanımlama bilgilerine eşzamansız erişim sağladığından ve doğrudan hizmet çalışanı tarafından kullanılabildiğinden, bu geçici çözüm artık onu destekleyen tarayıcılar için gerekli olmamalıdır.
Oluşturulmamış hizmet çalışanları için tuzaklar #
Herhangi bir statik önbelleğe alınmış dosya değişirse, hizmet çalışanı betiğinin değiştiğinden emin olun #
Yaygın bir PWA modeli, bir hizmet çalışanının, çalışması sırasında tüm statik uygulama dosyalarını yüklemesidir. install
İstemcilerin sonraki tüm ziyaretler için doğrudan Cache Storage API önbelleğine ulaşmasını sağlayan aşama. Hizmet çalışanları yalnızca tarayıcı, hizmet çalışanı komut dosyasının bir şekilde değiştiğini algıladığında kurulur, bu nedenle, önbelleğe alınmış bir dosya değiştiğinde hizmet çalışanı komut dosyası dosyasının kendisinin de bir şekilde değişmesini sağlamamız gerekiyordu. Bunu, hizmet çalışanı betiğimize statik kaynak dosya kümesinin bir karmasını yerleştirerek manuel olarak yaptık, böylece her sürüm ayrı bir hizmet çalışanı JavaScript dosyası üretti. Hizmet çalışanı kitaplıkları gibi çalışma kutusu bu süreci sizin için otomatikleştirin.
Birim testi #
Hizmet çalışanı API’leri, genel nesneye olay dinleyicileri ekleyerek çalışır. Örneğin:
self.addEventListener('fetch', (evt) => evt.respondWith(fetch('/foo')));
Bunu test etmek zahmetli olabilir çünkü olay tetikleyicisiyle, olay nesnesiyle dalga geçmeniz, respondWith()
geri arama ve ardından nihayet sonuç üzerinde iddiada bulunmadan önce sözü bekleyin. Bunu yapılandırmanın daha kolay bir yolu, tüm uygulamayı daha kolay test edilebilen başka bir dosyaya devretmektir.
import fetchHandler from './fetch_handler.js';
self.addEventListener('fetch', (evt) => evt.respondWith(fetchHandler(evt)));
Bir hizmet çalışanı betiğini birim testinin zorlukları nedeniyle, uygulamanın çoğunu diğer modüllere bölerek çekirdek hizmet çalışanı betiğini olabildiğince basit tuttuk. Bu dosyalar yalnızca standart JS modülleri olduğundan, standart test kitaplıklarıyla birim testi daha kolay yapılabilirdi.
2. ve 3. bölümler için takipte kalın #
Bu dizinin 2. ve 3. bölümlerinde medya yönetimi ve iOS’a özgü sorunlar hakkında konuşacağız. Google’da bir PWA oluşturma hakkında bize daha fazla soru sormak isterseniz, bizimle nasıl iletişime geçeceğinizi öğrenmek için yazar profillerimizi ziyaret edin: