Progresif Web Uygulamaları Geliştirme 02.0: Çevrimdışı hızlı başlangıç

Bu codelab, Google Developers Training ekibi tarafından geliştirilen Progresif Web Uygulamaları Geliştirme eğitim kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla tamamlamanız önerilir.

Kursla ilgili tüm ayrıntılar için Progresif web uygulamaları geliştirme genel bakış başlıklı makaleyi inceleyin.

Giriş

Bu laboratuvarda, bir web sitesini Progresif Web Uygulaması (PWA) standartları açısından denetlemek için Lighthouse'u kullanacaksınız. Ayrıca, hizmet çalışanı API'si ile çevrimdışı işlevsellik de ekleyeceksiniz.

Neler öğreneceksiniz?

  • Lighthouse ile siteleri denetleme
  • Uygulamaya çevrimdışı özellikler ekleme

Bilmeniz gerekenler

  • Temel HTML, CSS ve JavaScript
  • ES2015 Promises hakkında bilgi

İhtiyacınız olanlar

  • Terminal/kabuk erişimi olan bir bilgisayar
  • İnternet bağlantısı
  • Chrome Tarayıcı (Lighthouse'u kullanmak için)
  • Metin düzenleyici
  • İsteğe bağlı: Android cihazda Chrome

GitHub'dan pwa-training-labs deposunu indirin veya klonlayın ve gerekirse Node.js'nin LTS sürümünü yükleyin.

offline-quickstart-lab/app/ dizinine gidin ve yerel bir geliştirme sunucusu başlatın:

cd offline-quickstart-lab/app
npm install
node server.js

Sunucuyu Ctrl-c ile istediğiniz zaman sonlandırabilirsiniz.

Tarayıcınızı açıp localhost:8081/ adresine gidin. Sitenin basit ve statik bir web sayfası olduğunu görmeniz gerekir.

Not: Laboratuvarı etkilememeleri için tüm hizmet çalışanlarının kaydını iptal edin ve localhost için tüm hizmet çalışanı önbelleklerini temizleyin. Chrome Geliştirici Araçları'nda, Uygulama sekmesinin Depolamayı temizle bölümünden Site verilerini temizle'yi tıklayarak bunu yapabilirsiniz.

offline-quickstart-lab/app/ klasörünü tercih ettiğiniz metin düzenleyicide açın. Laboratuvarı app/ klasöründe oluşturacaksınız.

Bu klasörde şunlar bulunur:

  • images/ klasöründe örnek resimler var
  • styles/main.css, ana stil sayfasıdır.
  • index.html, örnek sitemizin ana HTML sayfasıdır.
  • package-lock.json ve package.json uygulama bağımlılıklarını izleyin (bu durumda bağımlılıklar yalnızca yerel geliştirme sunucusu içindir).
  • server.js, test için kullanılan yerel bir geliştirme sunucusudur.
  • service-worker.js, hizmet çalışanı dosyasıdır (şu anda boş)

Sitede değişiklik yapmaya başlamadan önce, nelerin iyileştirilebileceğini görmek için Lighthouse ile denetleme yapalım.

Uygulamaya (Chrome'da) dönün ve Geliştirici Araçları'nın Denetimler sekmesini açın. Lighthouse simgesini ve yapılandırma seçeneklerini görmelisiniz. Cihaz için "Mobil"i, tüm Denetimler'i, Sınırlama seçeneklerinden birini belirleyin ve Depolamayı temizle'yi seçin:

Denetimleri çalıştır'ı tıklayın. Denetimlerin tamamlanması birkaç dakika sürer.

Açıklama

Denetim tamamlandıktan sonra, geliştirici araçlarında puanların yer aldığı bir rapor görürsünüz. Aşağıdakine benzer bir skor gösterilmesi gerekir (skorlar tam olarak aynı olmayabilir):

Not: Lighthouse puanları yaklaşık değerlerdir ve ortamınızdan (ör. çok sayıda tarayıcı penceresi açıkken) etkilenebilir. Puanlarınız, burada gösterilenlerle tam olarak aynı olmayabilir.

Progresif web uygulaması bölümü de aşağıdaki gibi görünmelidir:

Rapor, beş kategoride puan ve metrik içerir:

  • Progresif web uygulaması
  • Performans
  • Erişilebilirlik
  • En İyi Uygulamalar
  • SEO

Gördüğünüz gibi, uygulamamız Progresif Web Uygulaması (PWA) kategorisinde düşük puan alıyor. Puanımızı yükseltelim.

Raporun PWA bölümüne göz atarak nelerin eksik olduğunu görün.

Hizmet çalışanı kaydetme

Raporda listelenen hatalardan biri, hizmet çalışanının kayıtlı olmamasıdır. Şu anda app/service-worker.js konumunda boş bir service worker dosyamız var.

Aşağıdaki komut dosyasını index.html öğesinin en altına, kapanış </body> etiketinden hemen önce ekleyin:

<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('service-worker.js')
      .then(reg => {
        console.log('Service worker registered! 😎', reg);
      })
      .catch(err => {
        console.log('😥 Service worker registration failed: ', err);
      });
  });
}
</script>

Açıklama

Bu kod, sayfa yüklendikten sonra boş service-worker.js hizmet çalışanı dosyasını kaydeder. Ancak mevcut hizmet çalışanı dosyası boş ve herhangi bir işlem yapmıyor. Sonraki adımda hizmet kodunu ekleyelim.

Kaynakları önceden önbelleğe alma

Raporda listelenen bir diğer hata ise uygulamanın çevrimdışıyken 200 durum koduyla yanıt vermemesidir. Bu sorunu çözmek için servis çalışanımızı güncellememiz gerekiyor.

Hizmet çalışanı dosyasına (service-worker.js) aşağıdaki kodu ekleyin:

const cacheName = 'cache-v1';
const precacheResources = [
  '/',
  'index.html',
  'styles/main.css',
  'images/space1.jpg',
  'images/space2.jpg',
  'images/space3.jpg'
];

self.addEventListener('install', event => {
  console.log('Service worker install event!');
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        return cache.addAll(precacheResources);
      })
  );
});

self.addEventListener('activate', event => {
  console.log('Service worker activate event!');
});

self.addEventListener('fetch', event => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(caches.match(event.request)
    .then(cachedResponse => {
        if (cachedResponse) {
          return cachedResponse;
        }
        return fetch(event.request);
      })
    );
});

Şimdi tarayıcıya dönüp siteyi yenileyin. Hizmet çalışanının aşağıdakileri yaptığını görmek için konsolu kontrol edin:

  • kayıtlı
  • yüklendi
  • Etkinleştirildi

Not: Hizmet çalışanını daha önce kaydettiyseniz veya tüm etkinliklerin tetiklenmesiyle ilgili sorun yaşıyorsanız tüm hizmet çalışanlarının kaydını silin ve sayfayı yenileyin. Bu işlem başarısız olursa uygulamanın tüm örneklerini kapatıp yeniden açın.

Ardından, Ctrl + c komutunu çalıştırarak komut satırınızdaki yerel geliştirme sunucusunu sonlandırın. Siteyi tekrar yenileyin ve sunucu çevrimdışı olsa bile sitenin yüklendiğini görün.

Not: Hizmet çalışanı getirilemediğini belirten bir konsol hatası görebilirsiniz: An unknown error occurred when fetching the script. service-worker.js Failed to load resource: net::ERR_CONNECTION_REFUSED. Bu hata, tarayıcı hizmet çalışanı komut dosyasını getiremediği (site çevrimdışı olduğu için) için gösterilir. Ancak hizmet çalışanını kendisini önbelleğe almak için kullanamadığımızdan bu durum beklenir. Aksi takdirde kullanıcının tarayıcısı, aynı hizmet çalışanıyla sonsuza kadar takılıp kalır.

Açıklama

Hizmet çalışanı, index.html içindeki kayıt komut dosyası tarafından kaydedildikten sonra hizmet çalışanı install etkinliği gerçekleşir. Bu etkinlik sırasında install etkinlik işleyicisi, adlandırılmış bir önbellek açar ve cache.addAll yöntemiyle belirtilen dosyaları önbelleğe alır. Bu işleme, genellikle kullanıcının sitenizi ilk kez ziyaret ettiği install etkinliği sırasında gerçekleştiği için "önbelleğe alma" adı verilir.

Bir hizmet çalışanı yüklendikten sonra ve sayfa şu anda başka bir hizmet çalışanı tarafından kontrol edilmiyorsa yeni hizmet çalışanı "etkinleştirilir" (hizmet çalışanında activate etkinlik işleyicisi tetiklenir) ve sayfayı kontrol etmeye başlar.

Etkinleştirilmiş bir servis çalışanı tarafından kontrol edilen bir sayfa kaynak istediğinde, istekler ağ proxy'si gibi servis çalışanından geçer. Her istek için bir fetch etkinliği tetiklenir. Service worker'ımızda fetch etkinlik işleyicisi, önbellekleri arar ve varsa önbelleğe alınmış kaynakla yanıt verir. Kaynak önbelleğe alınmamışsa kaynak normal şekilde istenir.

Kaynakların önbelleğe alınması, ağ isteklerini önleyerek uygulamanın çevrimdışı çalışmasına olanak tanır. Uygulamamız artık çevrimdışıyken 200 durum koduyla yanıt verebiliyor.

Not: Etkinleştirme etkinliği, bu örnekte oturum açma dışında hiçbir amaçla kullanılmaz. Etkinlik, hizmet çalışanı yaşam döngüsü sorunlarının hata ayıklanmasına yardımcı olmak için dahil edildi.

İsteğe bağlı: Önbelleğe alınan kaynakları, Geliştirici Araçları'nın Uygulama sekmesindeki Önbellek Depolama bölümünü genişleterek de görebilirsiniz:

Geliştirme sunucusunu node server.js ile yeniden başlatın ve siteyi yenileyin. Ardından, Geliştirici Araçları'nda Denetimler sekmesini tekrar açın ve Yeni Denetim'i (sol üst köşedeki artı işareti) seçerek Lighthouse denetimini yeniden çalıştırın. Denetleme tamamlandığında PWA puanımızın önemli ölçüde daha iyi olduğunu ancak yine de iyileştirilebileceğini göreceksiniz. Puanımızı iyileştirmeye bir sonraki bölümde devam edeceğiz.

Not: Web uygulaması yükleme banner'ı test etmek laboratuvarın kapsamı dışında olduğundan bu bölüm isteğe bağlıdır. Uzaktan hata ayıklama özelliğini kullanarak kendiniz deneyebilirsiniz.

PWA puanımız hâlâ iyi değil. Raporda listelenen diğer bazı başarısızlıklar ise kullanıcının web uygulamamızı yüklemeye yönlendirilmemesi ve adres çubuğunda bir başlangıç ekranı veya marka renkleri yapılandırmamış olmamızdır. Bu sorunları düzeltebilir ve bazı ek ölçütleri karşılayarak Ana Ekrana Ekle özelliğini kademeli olarak uygulayabiliriz. En önemlisi, manifest dosyası oluşturmamız gerekiyor.

Manifest dosyası oluşturma

app/ içinde manifest.json adlı bir dosya oluşturun ve aşağıdaki kodu ekleyin:

{
  "name": "Space Missions",
  "short_name": "Space Missions",
  "lang": "en-US",
  "start_url": "/index.html",
  "display": "standalone",
  "theme_color": "#FF9800",
  "background_color": "#FF9800",
  "icons": [
    {
      "src": "images/touch/icon-128x128.png",
      "sizes": "128x128"
    },
    {
      "src": "images/touch/icon-192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "images/touch/icon-256x256.png",
      "sizes": "256x256"
    },
    {
      "src": "images/touch/icon-384x384.png",
      "sizes": "384x384"
    },
    {
      "src": "images/touch/icon-512x512.png",
      "sizes": "512x512"
    }
  ]
}

Manifest'te referans verilen resimler uygulamada zaten sağlanmıştır.

Ardından, index.html içindeki <head> etiketinin en altına aşağıdaki HTML'yi ekleyin:

<link rel="manifest" href="manifest.json">

<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Space Missions">
<meta name="apple-mobile-web-app-title" content="Space Missions">
<meta name="theme-color" content="#FF9800">
<meta name="msapplication-navbutton-color" content="#FF9800">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="msapplication-starturl" content="/index.html">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="apple-touch-icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="icon" sizes="192x192" href="icon-192x192.png">
<link rel="apple-touch-icon" sizes="192x192" href="/images/touch/icon-192x192.png">
<link rel="icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="apple-touch-icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="apple-touch-icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="icon" sizes="512x512" href="/images/touch/icon-512x512.png">
<link rel="apple-touch-icon" sizes="512x512" href="/images/touch/icon-512x512.png">

Siteye geri dönün. Geliştirici Araçları'nın Uygulama sekmesinde Depolamayı temizle bölümünü seçin ve Site verilerini temizle'yi tıklayın. Ardından sayfayı yenileyin. Şimdi Manifest bölümünü seçin. manifest.json dosyasında yapılandırılan simgeleri ve yapılandırma seçeneklerini görmeniz gerekir. Değişikliklerinizi görmüyorsanız siteyi gizli pencerede açıp tekrar kontrol edin.

Açıklama

manifest.json dosyası, tarayıcıya uygulamanızın bazı aşamalı yönlerini (ör. tarayıcı çerçevesi, ana ekran simgesi ve başlangıç ekranı) nasıl stilize edip biçimlendireceğini söyler. Web uygulamanızı, yerel bir uygulama gibi standalone modunda (yani tarayıcının dışında) açılacak şekilde yapılandırmak için de kullanılabilir.

Bu yazı yazıldığı sırada bazı tarayıcılar için destek geliştirilme aşamasındaydı ve <meta> etiketleri, henüz tam desteğe sahip olmayan belirli tarayıcılarda bu özelliklerin bir alt kümesini yapılandırıyordu.

index.html'ın eski önbelleğe alınmış sürümünü kaldırmak için site verilerini temizlememiz gerekti (çünkü bu sürümde manifest bağlantısı yoktu). Başka bir Lighthouse denetimi çalıştırmayı deneyin ve PWA puanının ne kadar iyileştiğini görün.

Yükleme istemini etkinleştirme

Uygulamamızı yüklemek için bir sonraki adım, kullanıcılara yükleme istemini göstermektir. Chrome 67'de kullanıcılar otomatik olarak yönlendiriliyordu ancak Chrome 68'den itibaren yükleme istemi, kullanıcı hareketine yanıt olarak programatik bir şekilde etkinleştirilmelidir.

Aşağıdaki kodu kullanarak index.html öğesinin en üstüne (<main> etiketinden hemen sonra) "Uygulamayı yükle" düğmesi ve banner'ı ekleyin:

<section id="installBanner" class="banner">
    <button id="installBtn">Install app</button>
</section>

Ardından, styles/main.css öğesine aşağıdaki stilleri ekleyerek banner'ı şekillendirin:

.banner {
  align-content: center;
  display: none;
  justify-content: center;
  width: 100%;
}

Dosyayı kaydedin. Son olarak, aşağıdaki komut dosyası etiketini index.html'ya ekleyin:

  <script>
    let deferredPrompt;
    window.addEventListener('beforeinstallprompt', event => {

      // Prevent Chrome 67 and earlier from automatically showing the prompt
      event.preventDefault();

      // Stash the event so it can be triggered later.
      deferredPrompt = event;

      // Attach the install prompt to a user gesture
      document.querySelector('#installBtn').addEventListener('click', event => {

        // Show the prompt
        deferredPrompt.prompt();

        // Wait for the user to respond to the prompt
        deferredPrompt.userChoice
          .then((choiceResult) => {
            if (choiceResult.outcome === 'accepted') {
              console.log('User accepted the A2HS prompt');
            } else {
              console.log('User dismissed the A2HS prompt');
            }
            deferredPrompt = null;
          });
      });

      // Update UI notify the user they can add to home screen
      document.querySelector('#installBanner').style.display = 'flex';
    });
  </script>

Dosyayı kaydedin. Uzaktan hata ayıklama özelliğini kullanarak Android cihazdaki Chrome'da uygulamayı açın. Sayfa yüklendiğinde "Uygulamayı yükle" düğmesini görmeniz gerekir (masaüstünde görmezsiniz, bu nedenle mobil cihazda test ettiğinizden emin olun). Düğmeyi tıkladığınızda Ana ekrana ekle istemi açılır. Uygulamayı cihazınıza yükleme adımlarını uygulayın. Yükleme işleminden sonra, yeni oluşturulan ana ekran simgesine dokunarak web uygulamasını bağımsız modda (tarayıcı dışında) açabilirsiniz.

Açıklama

HTML ve CSS kodu, kullanıcıların yükleme istemini etkinleştirmesine izin vermek için kullanabileceğimiz gizli bir banner ve düğme ekler.

beforeinstallprompt etkinliği tetiklendikten sonra varsayılan deneyimi (Chrome 67 ve önceki sürümlerin kullanıcıları otomatik olarak yüklemeye yönlendirdiği deneyim) engelleriz ve beforeinstallevent değerini genel deferredPrompt değişkeninde yakalarız. Ardından, "Uygulamayı yükle" düğmesi, beforeinstallevent'nın prompt() yöntemiyle istemi gösterecek şekilde yapılandırılır. Kullanıcı bir seçim yaptıktan sonra (yükleme veya yüklememe) userChoice sözü, kullanıcının seçimiyle (outcome) yerine getirilir. Son olarak, her şey hazır olduğunda yükleme düğmesini gösteririz.

Lighthouse ile siteleri nasıl denetleyeceğinizi ve çevrimdışı işlevselliğin temellerini nasıl uygulayacağınızı öğrendiniz. İsteğe bağlı bölümleri tamamladıysanız web uygulamalarını ana ekrana nasıl yükleyeceğinizi de öğrendiniz.

Diğer kaynaklar

Lighthouse açık kaynaktır. Bu depoyu çatallayabilir, kendi testlerinizi ekleyebilir ve hataları bildirebilirsiniz. Lighthouse, derleme süreçleriyle entegrasyon için komut satırı aracı olarak da kullanılabilir.

PWA eğitim kursundaki tüm codelab'leri görmek için kursun Hoş geldiniz codelab'ine göz atın.