mirror of
https://github.com/a2nt/silverstripe-progressivewebapp.git
synced 2024-10-22 11:05:45 +02:00
Service worker
This commit is contained in:
parent
a747fb2362
commit
b435128ac0
@ -3,6 +3,11 @@
|
|||||||
namespace MichelSteege\ProgressiveWebApp\Controllers;
|
namespace MichelSteege\ProgressiveWebApp\Controllers;
|
||||||
|
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\ORM\ArrayList;
|
||||||
|
use SilverStripe\View\ArrayData;
|
||||||
|
use SilverStripe\Core\ClassInfo;
|
||||||
|
use MichelSteege\ProgressiveWebApp\Interfaces\ServiceWorkerCacheProvider;
|
||||||
|
|
||||||
class ServiceWorkerController extends Controller {
|
class ServiceWorkerController extends Controller {
|
||||||
|
|
||||||
@ -12,6 +17,11 @@ class ServiceWorkerController extends Controller {
|
|||||||
private static $allowed_actions = [
|
private static $allowed_actions = [
|
||||||
'index'
|
'index'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @config
|
||||||
|
*/
|
||||||
|
private static $debug_mode = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default controller action for the service-worker.js file
|
* Default controller action for the service-worker.js file
|
||||||
@ -22,5 +32,44 @@ class ServiceWorkerController extends Controller {
|
|||||||
$this->getResponse()->addHeader('Content-Type', 'application/javascript; charset="utf-8"');
|
$this->getResponse()->addHeader('Content-Type', 'application/javascript; charset="utf-8"');
|
||||||
return $this->renderWith('ServiceWorker');
|
return $this->renderWith('ServiceWorker');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base URL
|
||||||
|
* @return varchar
|
||||||
|
*/
|
||||||
|
public function BaseUrl() {
|
||||||
|
return Director::baseURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug mode
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function DebugMode() {
|
||||||
|
if(Director::isDev()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return $this->config()->get('debug_mode');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list with file to cache in the install event
|
||||||
|
* @return ArrayList
|
||||||
|
*/
|
||||||
|
public function CacheOnInstall() {
|
||||||
|
$paths = [];
|
||||||
|
foreach(ClassInfo::implementorsOf(ServiceWorkerCacheProvider::class) as $class){
|
||||||
|
foreach($class::getServiceWorkerCachedPaths() as $path){
|
||||||
|
$paths[] = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$list = new ArrayList();
|
||||||
|
foreach($paths as $path){
|
||||||
|
$list->push(new ArrayData([
|
||||||
|
'Path' => $path
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
9
src/Interfaces/ServiceWorkerCacheProvider.php
Normal file
9
src/Interfaces/ServiceWorkerCacheProvider.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MichelSteege\ProgressiveWebApp\Interfaces;
|
||||||
|
|
||||||
|
interface ServiceWorkerCacheProvider {
|
||||||
|
|
||||||
|
public static function getServiceWorkerCachedPaths();
|
||||||
|
|
||||||
|
}
|
@ -1,26 +1,121 @@
|
|||||||
self.addEventListener('install', function(e) {
|
<%--<script>//Ugly fix for code highlights--%>
|
||||||
console.log('Install');
|
var version = 'v1::';
|
||||||
/*
|
var debug = <% if $DebugMode %>true<% else %>false<% end_if %>;
|
||||||
e.waitUntil(
|
|
||||||
caches.open('airhorner').then(function(cache) {
|
/**
|
||||||
return cache.addAll([
|
* Console.log proxy for quick enabling/disabling
|
||||||
'/',
|
*/
|
||||||
'/index.html',
|
function log(msg){
|
||||||
'/index.html?homescreen=1',
|
if(debug){
|
||||||
'/?homescreen=1',
|
console.log(msg);
|
||||||
'/styles/main.css',
|
}
|
||||||
'/scripts/main.min.js',
|
}
|
||||||
'/sounds/airhorn.mp3'
|
|
||||||
]);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
|
|
||||||
self.addEventListener('fetch', function(event) {
|
/**
|
||||||
console.log(event.request.url);
|
* Service worker installation
|
||||||
});
|
*/
|
||||||
|
self.addEventListener('install', function (event) {
|
||||||
|
log('Service worker: install start');
|
||||||
|
event.waitUntil(caches.open(version + 'fundamentals').then(function (cache) {
|
||||||
|
//Install all required pages/assets
|
||||||
|
return cache.addAll([
|
||||||
|
'$BaseUrl'<% if $CacheOnInstall %>,<% end_if %>
|
||||||
|
<% if $CacheOnInstall %>
|
||||||
|
<% loop $CacheOnInstall %>
|
||||||
|
'$Path'<% if not $Last %>,<% end_if %>
|
||||||
|
<% end_loop %>
|
||||||
|
<% end_if %>
|
||||||
|
]);
|
||||||
|
}).then(function () {
|
||||||
|
log('Service worker: install completed');
|
||||||
|
}).catch(function(){
|
||||||
|
log('Service worker: install failed');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
self.addEventListener('beforeinstallprompt', function(event) {
|
/**
|
||||||
console.log('beforeinstallprompt');
|
* Service worker activation
|
||||||
});
|
*/
|
||||||
|
self.addEventListener('activate', function (event) {
|
||||||
|
log('Service worker: activate start');
|
||||||
|
event.waitUntil(caches.keys().then(function (keys) {
|
||||||
|
//Remove old cache entries
|
||||||
|
return Promise.all(keys.filter(function (key) {
|
||||||
|
return !key.startsWith(version);
|
||||||
|
}).map(function (key) {
|
||||||
|
return caches.delete(key);
|
||||||
|
}));
|
||||||
|
}).then(function () {
|
||||||
|
log('Service worker: activate completed');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch handler
|
||||||
|
*/
|
||||||
|
self.addEventListener('fetch', function (event) {
|
||||||
|
//We are only interested in get requests
|
||||||
|
if (event.request.method !== 'GET') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse the url
|
||||||
|
var requestURL = new URL(event.request.url);
|
||||||
|
|
||||||
|
//Test for images
|
||||||
|
if (/\.(jpg|jpeg|png|gif|webp)$/.test(requestURL.pathname)) {
|
||||||
|
log('Service worker: skip image ' + event.request.url);
|
||||||
|
//For now we skip images but change this later to maybe some caching and/or an offline fallback
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for our own urls
|
||||||
|
if (requestURL.origin == location.origin) {
|
||||||
|
//All our own urls are following this route:
|
||||||
|
//-If there is cache serve from cache but also update the cache from the network
|
||||||
|
//-If there is no cache then get from the network and put in the cache
|
||||||
|
//-If both fail fallback to a generic offline message
|
||||||
|
event.respondWith(caches.match(event.request).then(function (cached) {
|
||||||
|
var networked = fetch(event.request).then(fetchedFromNetwork, unableToResolve).catch(unableToResolve);
|
||||||
|
log('Service worker: fetch event ' + (cached ? '(cached)' : '(network)') + ' - ' + event.request.url);
|
||||||
|
return cached || networked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetched from network handler
|
||||||
|
*/
|
||||||
|
function fetchedFromNetwork(response) {
|
||||||
|
var cacheCopy = response.clone();
|
||||||
|
log('Service worker fetch from network - ' + event.request.url);
|
||||||
|
caches.open(version + 'pages').then(function add(cache) {
|
||||||
|
cache.put(event.request, cacheCopy);
|
||||||
|
}).then(function () {
|
||||||
|
log('Service worker: fetch response stored in cache - ' + event.request.url);
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No internet and no cache handler
|
||||||
|
*/
|
||||||
|
function unableToResolve(error) {
|
||||||
|
log('Service worker: fetch request failed in both cache and network ' + error);
|
||||||
|
return new Response('<h1>Service Unavailable</h1>', {
|
||||||
|
status: 503,
|
||||||
|
statusText: 'Service Unavailable',
|
||||||
|
headers: new Headers({
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//All others, nothing special here
|
||||||
|
log('Service worker: other url - ' + event.request.url);
|
||||||
|
event.respondWith(caches.match(event.request).then(function(response) {
|
||||||
|
return response || fetch(event.request);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
//<%--Ugly fix for code highlights</script>--%>
|
Loading…
Reference in New Issue
Block a user