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:
- manifest.json
- sw.js
- 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:
- https://web.dev/progressive-web-apps/
- https://web.dev/extending-workbox/
- https://developers.google.com/web/tools/workbox/guides/get-started
- What are Progressive Web Apps?
- How Progressive Web Apps can drive business success
- What makes a good Progressive Web App?
- What does it take to be installable?
- How to define your install strategy
- Add a web app manifest
- Create an offline fallback page
- How to provide your own in-app install experience
- Patterns for promoting PWA installation
- Using a PWA in your Android app
- Make it installable
- Make your PWA feel more like an app
- Progressively enhance your Progressive Web App
- Get things done quickly with app shortcuts
- Badging for app icons
- Receiving shared data with the Web Share Target API
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.