Kategoriler
WordPress

WordPress sitenizi Workbox ile çalıştırmak (PWA)

Workbox kullanarak WordPress sitesini PWA uyumlu hale getiriyoruz.

Burada WordPress sitesi için Workbox kullanarak siteyi basitçe PWA uygulaması haline çevirmeyi anlatacağım. Eğer kodlama ile ilgilenmiyorsanız bana ulaşabilirsiniz sizin için yapabilirim.

Progressive Web Apps(PWA) nedir ve detaylı bilgi almak için: https://wolkanca.com/pwa-app-gelistirme/ yazımı okuyabilirsiniz. PWA, Google tarafından tavsiye edilmekte ve SEO noktasında siteye + puan vermektedir, özellikle günümüzde mobil kullanımın %80’ler üzerinde olduğu ve Google’ın Mobile First politikası düşünüldüğünde WordPress sitenizi PWA uyumlu yapmak SEO için gerçekten maliyetsiz ve hemen yapılması gereken şeylerden biri.

Eğer benim aşağıda anlatacağım özel versiyonu kullanmak istemiyorsanız ve bir WordPress eklentisi ile bunu yapmak isterseniz https://wordpress.org/plugins/tags/pwa/ adresinden PWA eklentilerinden birini kullanın, ancak ben yaptığım sitelerde çok önemli değilse eklenti kullanmamayı yeğliyorum zira eklentilerde çıkan açıklar yüzünden sitelerde güvenlik riskleri oluşuyor ve bu WordPress eklentilerinde sürekli olan bir şey.

WordPress’e Workbox ile PWA yapmak

Benim özel uygulamamda 3 dosyaya ihtiyaç vardır, bunlar:

  1. manifest.json
  2. sw.js
  3. offline.html

Ayrıca manifest.json içerisindeki .png dosyalarını da sitenizin ana dizinine yerleştirmeniz gerekir.

manifest.json içeriği:

{
 "name": "WOLKANCA",
 "short_name": "WOLKANCA", 
 "description": "Volkan Yılmaz'ın blogudur. Ağırlıklı olarak Dijital pazarlama, WordPress ve SEO konularında yazılar bulunmakla birlikte web ile ilgili çeşitli içerikleri barındırır",
 "lang": "tr",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "display": "fullscreen",
  "orientation": "portrait",
  "scope": "/",
  "start_url": "/",
 "icons": [
 {
   "src": "\/android-icon-36x36.png",
   "sizes": "36x36",
   "type": "image\/png",
   "density": "0.75"
 },
 {
   "src": "\/android-icon-48x48.png",
   "sizes": "48x48",
   "type": "image\/png",
   "density": "1.0"
 },
 {
   "src": "\/android-icon-72x72.png",
   "sizes": "72x72",
   "type": "image\/png",
   "density": "1.5"
 },
 {
   "src": "\/android-icon-96x96.png",
   "sizes": "96x96",
   "type": "image\/png",
   "density": "2.0"
 },
 {
   "src": "\/android-icon-144x144.png",
   "sizes": "144x144",
   "type": "image\/png",
   "density": "3.0"
 },
 {
   "src": "\/android-icon-192x192.png",
   "sizes": "192x192",
   "type": "image\/png",
   "purpose": "any maskable",
   "density": "4.0"
 },
 {
   "src": "\/android-icon-512x512.png",
   "sizes": "512x512",
   "type": "image\/png",
   "density": "5.0"
 }
 ]
}

sw.js içeriği:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.1.5/workbox-sw.js');
if (workbox){
	workbox.core.skipWaiting();
	workbox.core.clientsClaim();
    workbox.googleAnalytics.initialize();
    workbox.precaching.precacheAndRoute([{url: '/offline.html', revision: null},{url: '/?precache=1', revision: null}],{cleanUrls: false,},{directoryIndex: null,},{ignoreURLParametersMatching:[/.*/]});
    workbox.routing.registerRoute(new RegExp('.*/wp-admin/.*|.*/wp-includes/.*|/.*\\.php'), new workbox.strategies.NetworkOnly());
    workbox.routing.registerRoute(({
        url
   }) => url.origin === 'https://fonts.googleapis.com' || url.origin === 'https://fonts.gstatic.com', new workbox.strategies.CacheFirst({
        cacheName: 'google-cdn-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 32,
            maxAgeSeconds: 60 * 60 * 24 * 365
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*\\.(?:woff|woff2|eot|otf|ttc|ttf)$'), new workbox.strategies.CacheFirst({
        cacheName: 'fonts-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 32,
            maxAgeSeconds: 60 * 60 * 24 * 365
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*\\.js$'), new workbox.strategies.CacheFirst({
        cacheName: 'js-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 32,
            maxAgeSeconds: 30 * 24 * 60 * 60
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*\\.css$'), new workbox.strategies.CacheFirst({
        cacheName: 'css-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 32,
            maxAgeSeconds: 30 * 24 * 60 * 60
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*\\.(?:png|ico|jpg|jpeg|svg|gif|webp|mp4|mp3|webm|mpeg)$'), new workbox.strategies.CacheFirst({
        cacheName: 'media-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 512,
            maxAgeSeconds: 30 * 24 * 60 * 60,
            purgeOnQuotaError: true
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*\\.webmanifest$|/.*\\.json$|/.*\\.xml$|/.*\\.html$|/.*\\.htm$|/.*\\.txt$|/.*\\.pdf$|/.*\\?.*'), new workbox.strategies.CacheFirst({
        cacheName: 'diger-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 512,
            maxAgeSeconds: 30 * 24 * 60 * 60,
            purgeOnQuotaError: true
       })],
   }));
    workbox.routing.registerRoute(new RegExp('/.*/'), new workbox.strategies.StaleWhileRevalidate({
        cacheName: 'page-cache',
        plugins: [new workbox.expiration.ExpirationPlugin({
            maxEntries: 512,
            maxAgeSeconds: 7 * 24 * 60 * 60,
            purgeOnQuotaError: true
       })],
   }));
}else{
    console.log('Boo! Workbox patlamış 🤦');
}
/* 
wolkanca@gmail.com - Haziran 2021 
https://wolkanca.com/humans.txt 
*/

sw.js de ben WordPress ile uyumlu kurallar yazdım, ayrıca Google Analytics eklentisi ve precaching ile ana sayfayı ve offline.html siteye ilk girişte direk önbelleğe alınmakta, siz ekstra olarak istediğiniz gibi geliştirebilirsiniz, https://developers.google.com/web/tools/workbox/ adresinde tüm bilgiler mevcuttur ve Workbox son versiyonu 6.0.2 kullandım buna dikkat etmelisiniz.

offline.html içeriği

<!DOCTYPE html>
<html lang="tr">
<head>
  <meta charset="UTF-8">
  <meta id="viewport" name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi">
  <title>Offline</title>
<meta name="robots" content="noindex">
<link rel="manifest" href="/manifest.json">
</head>
<body>
<div>
<h1>Şu an offline</h1>
<p>Sanırım bağlantımız kesildi dostum, sonra yeniden görüşelim.</p>
<p><a href="/">Volkan Yılmaz</a></p>
</div>
</body>
</html>

offline.html eğer siteye internet bağlantısı olamayan bir cihazla girilirse gösterilmek üzere bir boş sayfa diyebiliriz, çok mühim değil aslında.

Bu 3 dosyayı oluşturup sitenizin ana dizinine yükleyin. Ardından sw.js çalıştırmak için sitenizin sayfalarına aşağıdaki gibi bir script eklemek gerekir:

/*giris yapılmış ise no cache*/
if (navigator.cookieEnabled && 'serviceWorker' in navigator ){
var cookiewolkanca = document.cookie.indexOf('wp-settings-time') !== -1; 
if(cookiewolkanca){//alert("Hello Admin!");
caches.keys().then(cacheNames =>{cacheNames.forEach(cacheName =>{caches.delete(cacheName);});}); navigator.serviceWorker.getRegistrations().then( function(registrations){for(let registration of registrations){registration.unregister();}}); 
}else{
            window.addEventListener('load', function(){
                navigator.serviceWorker.register('/sw.js').then(
                function(registration){},
                function(err){
                    console.log('ServiceWorker kaydedemedi: ', err);
               });
           });

}
}

Ayrıca sitenizin head kısmına da aşağıdakini eklemelisiniz:

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

sw.js çalıştıran scripti ve manifest.json head meta etiketini manuel olarak kullandığınız WordPress temasına ekleyebileceğiniz gibi dilerseniz aşağıdaki fonksiyonu temanızın function.php dosyasına yazarak sitenin tüm sayfalarına otomatik eklenmesini sağlayabilirsiniz:

add_action('wp_head', 'manifest_header', 2); 
function manifest_header(){
echo '<link rel="manifest" href="/manifest.json">';
}
add_action( 'admin_footer', 'admin_footer' );
function admin_footer(){
/*ServiceWorker unregister / admin panelde cache sil*/
echo '<script>if (navigator.cookieEnabled && "serviceWorker" in navigator ){caches.keys().then(cacheNames =>{cacheNames.forEach(cacheName =>{caches.delete(cacheName);});}); navigator.serviceWorker.getRegistrations().then( function(registrations){for(let registration of registrations){registration.unregister();}});}</script>';
}
add_action('wp_footer', 'sw_js');
function sw_js(){?>
<script>
/*giris yapılmış ise no cache*/
if (navigator.cookieEnabled && 'serviceWorker' in navigator ){
var cookiewolkanca = document.cookie.indexOf('wp-settings-time') !== -1; 
if(cookiewolkanca){//alert("Hello Admin!");
caches.keys().then(cacheNames =>{cacheNames.forEach(cacheName =>{caches.delete(cacheName);});}); navigator.serviceWorker.getRegistrations().then( function(registrations){for(let registration of registrations){registration.unregister();}}); 
}else{
            window.addEventListener('load', function(){
                navigator.serviceWorker.register('/sw.js').then(
                function(registration){},
                function(err){
                    console.log('ServiceWorker kaydedemedi: ', err);
               });
           });

}
}
</script>
<?php}

Test etmek

Hepsi bu kadar.

Not: PWA sadece HTTPS ile çalışır, SSL yüklü olmayan bir sitede çalışmayacaktır. E-ticaret siteleri için PWA özellikle tavsiye ederim zira alışverişte sepete ekleme ve ödeme kısmında önemli bir hız kazanabilirsiniz bu da satış performansını yükseltir, Workbox bir JavaScript kütüphanesidir.

Kaynaklar:

Extending Workbox: Custom strategies and plugins

Not: eğer sitenin sadece belirli sayfalarını önbelleğe alıp diğer her şeyi normal çalıştırmak isterseniz sw.js dosyanızı şu örnekteki gibi yapabilirsiniz:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.1.5/workbox-sw.js');
if (workbox){
	workbox.core.skipWaiting();
	workbox.core.clientsClaim();
    workbox.googleAnalytics.initialize();
    workbox.precaching.precacheAndRoute([{url: '/offline.html', revision: null},{url: '/?precache=1', revision: null}],{cleanUrls: false,},{directoryIndex: null,},{ignoreURLParametersMatching:[/.*/]});
}else{
    console.log('Boo! Workbox patlamış 🤦');
}

Yukarıdaki kod sadece /offline.html ve ana sayfa /?precache=1 olarak önbelleğe alacak diğer her şey normal önbellek olmadan çalışır.