-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
234 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,91 +1,226 @@ | ||
import { addLangs } from 'consts'; | ||
|
||
const CACHE_NAME = 'interslavic-dictionary'; | ||
const cacheUrls = [ | ||
'index.html', | ||
'data/basic.json', | ||
'data/translateStatistic.json', | ||
...addLangs.map((lang) => `data/${lang}.json`), | ||
'grammarComponent.js', | ||
'communityComponent.js', | ||
'index.js', | ||
'sw.js', | ||
'styles/grammarComponent.css', | ||
'styles/communityComponent.css', | ||
'styles/index.css', | ||
const urlsToPrefetch = [ | ||
'/', | ||
'/data/basic.json', | ||
'/data/translateStatistic.json', | ||
...addLangs.map((lang) => `/data/${lang}.json`), | ||
'/grammarComponent.js', | ||
'/communityComponent.js', | ||
'/index.js', | ||
'/sw.js', | ||
'/styles/grammarComponent.css', | ||
'/styles/communityComponent.css', | ||
'/styles/index.css', | ||
'/icons/android-icon-36x36.png', | ||
'/icons/android-icon-48x48.png', | ||
'/icons/android-icon-72x72.png', | ||
'/icons/android-icon-96x96.png', | ||
'/icons/android-icon-144x144.png', | ||
'/icons/android-icon-192x192.png', | ||
'/icons/apple-icon.png', | ||
'/icons/apple-icon-57x57.png', | ||
'/icons/apple-icon-60x60.png', | ||
'/icons/apple-icon-72x72.png', | ||
'/icons/apple-icon-76x76.png', | ||
'/icons/apple-icon-114x114.png', | ||
'/icons/apple-icon-120x120.png', | ||
'/icons/apple-icon-144x144.png', | ||
'/icons/apple-icon-152x152.png', | ||
'/icons/apple-icon-180x180.png', | ||
'/icons/apple-icon-precomposed.png', | ||
'/icons/discord-icon-330x102.png', | ||
'/icons/favicon.ico', | ||
'/icons/favicon-16x16.png', | ||
'/icons/favicon-32x32.png', | ||
'/icons/favicon-96x96.png', | ||
'/icons/icon-72x72.png', | ||
'/icons/icon-96x96.png', | ||
'/icons/icon-128x128.png', | ||
'/icons/icon-144x144.png', | ||
'/icons/icon-152x152.png', | ||
'/icons/icon-192x192.png', | ||
'/icons/icon-384x384.png', | ||
'/icons/icon-512x512.png', | ||
'/icons/manifest.json', | ||
'/icons/ms-icon-70x70.png', | ||
'/icons/ms-icon-144x144.png', | ||
'/icons/ms-icon-150x150.png', | ||
'/icons/ms-icon-310x310.png', | ||
]; | ||
|
||
self.addEventListener('install', (event: any) => { | ||
const version = '1.0.0' | ||
|
||
self.addEventListener("install", (event: any) => { | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: install event in progress.'); | ||
event.waitUntil( | ||
caches.open(CACHE_NAME).then((cache) => cache.addAll(cacheUrls)) | ||
/* The caches built-in is a promise-based API that helps you cache responses, | ||
as well as finding and deleting them. | ||
*/ | ||
caches | ||
/* You can open a cache by name, and this method returns a promise. We use | ||
a versioned cache name here so that we can remove old cache entries in | ||
one fell swoop later, when phasing out an older service worker. | ||
*/ | ||
.open(version + 'fundamentals') | ||
.then(function(cache) { | ||
/* After the cache is opened, we can fill it with the offline fundamentals. | ||
The method below will add all resources we've indicated to the cache, | ||
after making HTTP requests for each of them. | ||
*/ | ||
return cache.addAll(urlsToPrefetch); | ||
}) | ||
.then(function() { | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: install completed'); | ||
}) | ||
); | ||
}); | ||
|
||
self.addEventListener("activate", (event: any) => { | ||
async function deleteOldCaches() { | ||
// List all caches by their names. | ||
const names = await caches.keys(); | ||
await Promise.all(names.map(name => { | ||
if (name !== CACHE_NAME) { | ||
// If a cache's name is the current name, delete it. | ||
return caches.delete(name); | ||
} | ||
})); | ||
self.addEventListener("fetch", (event: any) => { | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch event in progress.'); | ||
|
||
/* We should only cache GET requests, and deal with the rest of method in the | ||
client-side, by handling failed POST,PUT,PATCH,etc. requests. | ||
*/ | ||
if (event.request.method !== 'GET') { | ||
/* If we don't block the event as shown below, then the request will go to | ||
the network as usual. | ||
*/ | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch event ignored.', event.request.method, event.request.url); | ||
|
||
return; | ||
} | ||
/* Similar to event.waitUntil in that it blocks the fetch event on a promise. | ||
Fulfillment result will be used as the response, and rejection will end in a | ||
HTTP response indicating failure. | ||
*/ | ||
event.respondWith( | ||
caches | ||
/* This method returns a promise that resolves to a cache entry matching | ||
the request. Once the promise is settled, we can then provide a response | ||
to the fetch request. | ||
*/ | ||
.match(event.request) | ||
.then(function(cached) { | ||
/* Even if the response is in our cache, we go to the network as well. | ||
This pattern is known for producing "eventually fresh" responses, | ||
where we return cached responses immediately, and meanwhile pull | ||
a network response and store that in the cache. | ||
Read more: | ||
https://ponyfoo.com/articles/progressive-networking-serviceworker | ||
*/ | ||
const networked = fetch(event.request) | ||
// We handle the network request with success and failure scenarios. | ||
.then(fetchedFromNetwork, unableToResolve) | ||
// We should catch errors on the fetchedFromNetwork handler as well. | ||
.catch(unableToResolve); | ||
|
||
event.waitUntil(deleteOldCaches()); | ||
}); | ||
/* We return the cached response immediately if there is one, and fall | ||
back to waiting on the network as usual. | ||
*/ | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch event', cached ? '(cached)' : '(network)', event.request.url); | ||
|
||
window.addEventListener("online", () => { | ||
// eslint-disable-next-line no-console | ||
console.log("You are online!"); | ||
}); | ||
window.addEventListener("offline",() => { | ||
// eslint-disable-next-line no-console | ||
console.log("Network connection lost!"); | ||
}); | ||
return cached || networked; | ||
|
||
const MAX_AGE = 1000 * 60 * 10; // 10 minutes. | ||
function fetchedFromNetwork(response: any) { | ||
/* We copy the response before replying to the network request. | ||
This is the response that will be stored on the ServiceWorker cache. | ||
*/ | ||
const cacheCopy = response.clone(); | ||
|
||
self.addEventListener('fetch', (event: any) => { | ||
event.respondWith( | ||
// Trying find resource in cache. | ||
caches.match( | ||
event.request, | ||
{ | ||
ignoreSearch: event.request.url.indexOf('?') != -1, | ||
}, | ||
).then((cachedResponse) => { | ||
let lastModified; | ||
let fetchRequest; | ||
|
||
// If exist. | ||
if (cachedResponse) { | ||
// Get date of last update. | ||
lastModified = new Date(cachedResponse.headers.get('last-modified')); | ||
// If it is expired | ||
if (lastModified && (Date.now() - lastModified.getTime()) > MAX_AGE) { | ||
fetchRequest = event.request.clone(); | ||
|
||
// Cretae new. | ||
return fetch(fetchRequest).then((response) => { | ||
// If error then load from cache. | ||
if (!response || response.status !== 200) { | ||
return cachedResponse; | ||
} | ||
// Update cache. | ||
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, response)); | ||
|
||
// Return new data. | ||
return response.clone(); | ||
}).catch(() => cachedResponse); | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch response from network.', event.request.url); | ||
|
||
caches | ||
// We open a cache to store the response for this request. | ||
.open(version + 'pages') | ||
.then(function add(cache) { | ||
/* We store the response for this request. It'll later become | ||
available to caches.match(event.request) calls, when looking | ||
for cached responses. | ||
*/ | ||
cache.put(event.request, cacheCopy); | ||
}) | ||
.then(function() { | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch response stored in cache.', event.request.url); | ||
}); | ||
|
||
// Return the response so that the promise is settled in fulfillment. | ||
return response; | ||
} | ||
|
||
/* When this method is called, it means we were unable to produce a response | ||
from either the cache or the network. This is our opportunity to produce | ||
a meaningful response even when all else fails. It's the last chance, so | ||
you probably want to display a "Service Unavailable" view or a generic | ||
error response. | ||
*/ | ||
function unableToResolve () { | ||
/* There's a couple of things we can do here. | ||
- Test the Accept header and then return one of the `offlineFundamentals` | ||
e.g: `return caches.match('/some/cached/image.png')` | ||
- You should also consider the origin. It's easier to decide what | ||
"unavailable" means for requests against your origins than for requests | ||
against a third party, such as an ad provider | ||
- Generate a Response programmaticaly, as shown below, and return that | ||
*/ | ||
|
||
// eslint-disable-next-line no-console | ||
console.log('WORKER: fetch request failed in both cache and network.'); | ||
|
||
/* Here we're creating a response programmatically. The first parameter is the | ||
response body, and the second one defines the options for the response. | ||
*/ | ||
return new Response('<h1>Service Unavailable</h1>', { | ||
status: 503, | ||
statusText: 'Service Unavailable', | ||
headers: new Headers({ | ||
'Content-Type': 'text/html' | ||
}) | ||
}); | ||
} | ||
|
||
return cachedResponse; | ||
} | ||
}) | ||
); | ||
}); | ||
|
||
self.addEventListener("activate", (event: any) => { | ||
/* Just like with the install event, event.waitUntil blocks activate on a promise. | ||
Activation will fail unless the promise is fulfilled. | ||
*/ | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: activate event in progress.'); | ||
|
||
// Request from network. | ||
return fetch(event.request); | ||
}) | ||
event.waitUntil( | ||
caches | ||
/* This method returns a promise which will resolve to an array of available | ||
cache keys. | ||
*/ | ||
.keys() | ||
.then(function (keys) { | ||
// We return a promise that settles when all outdated caches are deleted. | ||
return Promise.all( | ||
keys | ||
.filter(function (key) { | ||
// Filter by keys that don't start with the latest version prefix. | ||
return !key.startsWith(version); | ||
}) | ||
.map(function (key) { | ||
/* Return a promise that's fulfilled | ||
when each outdated cache is deleted. | ||
*/ | ||
return caches.delete(key); | ||
}) | ||
); | ||
}) | ||
.then(function() { | ||
// eslint-disable-next-line no-console | ||
console.log('WORKER: activate completed.'); | ||
}) | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.