From e7bc06b770cca56ef00768dfc9ba1ac295a916ae Mon Sep 17 00:00:00 2001 From: nerdeveloper Date: Thu, 10 Oct 2019 18:50:03 +0100 Subject: [PATCH] fix(sw.js): fix cache store fix cache store that cache svery request on current page --- .travis.yml | 3 - public/sw.js | 222 +++++++++++++-------------------------------------- src/app.ts | 12 --- 3 files changed, 55 insertions(+), 182 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5a4d663..f83deb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,6 @@ sudo: false language: node_js node_js: - "10" -branches: - only: - - master notifications: email: false diff --git a/public/sw.js b/public/sw.js index 898fc4e..9cb2968 100755 --- a/public/sw.js +++ b/public/sw.js @@ -1,180 +1,68 @@ -/* eslint-disable @typescript-eslint/no-use-before-define */ -//This is the service worker with the Advanced caching - -const CACHE = "pwabuilder-adv-cache"; -const precacheFiles = [ - /* Add an array of files to precache for your app */ -]; - -// TODO: replace the following with the correct offline fallback page i.e.: const offlineFallbackPage = "offline.html"; -const offlineFallbackPage = "ToDo-replace-this-name.html"; - -const networkFirstPaths = [ - /* Add an array of regex of paths that should go network first */ - // Example: /\/api\/.*/ -]; - -const avoidCachingPaths = [ - /* Add an array of regex of paths that shouldn't be cached */ - // Example: /\/api\/.*/ - /\/Images\/.*/, - /\/free\/.*/, - /\/bootstrap\/.*/, - /\/user\/.*/, - /\/ajax\/.*/, - /\/repos\/.*/, - /\/recaptcha\/.*/, - /\/auth\/.*/, - /\/socket.io\/.*/, - /\/avatar\/.*/, - /\/delete\/.*/, - /\/create\/.*/, - - "https://source.unsplash.com", - "https://code.jquery.com/jquery-3.2.1.slim.min.js", +const CACHE_NAME = "pwabuilder-adv-cache"; +const {INSTALL, FETCH} = { + INSTALL: "install", + FETCH: "fetch", +}; +const URLS_TO_CACHE = [ + "./", + "./dist/style.css", + "./dist/App.bundle.js", + "./sw.js", + "./pwabuilder.js", + "./manifest.json", "https://buttons.github.io/buttons.js", ]; - -function pathComparer(requestUrl, pathRegEx) { - return requestUrl.match(new RegExp(pathRegEx)); -} - -function comparePaths(requestUrl, pathsArray) { - if (requestUrl) { - for (let index = 0; index < pathsArray.length; index++) { - const pathRegEx = pathsArray[index]; - if (pathComparer(requestUrl, pathRegEx)) { - return true; - } - } +const preLoad = async () => { + console.log("Installing web app"); + try { + const cache = await caches.open(CACHE_NAME); + const cachedUrls = cache.addAll(URLS_TO_CACHE); + return cachedUrls; + } catch (error) { + console.error(error); } +}; - return false; -} - -self.addEventListener("install", function(event) { - console.log("[PWA Builder] Install Event processing"); - - console.log("[PWA Builder] Skip waiting on install"); +self.addEventListener(INSTALL, event => { self.skipWaiting(); - - event.waitUntil( - caches.open(CACHE).then(function(cache) { - console.log("[PWA Builder] Caching pages during install"); - - return cache.addAll(precacheFiles).then(function() { - if (offlineFallbackPage === "ToDo-replace-this-name.html") { - return cache.add( - new Response( - "TODO: Update the value of the offlineFallbackPage constant in the serviceworker.", - ), - ); - } - - return cache.add(offlineFallbackPage); - }); - }), - ); -}); - -// Allow sw to control of current page -self.addEventListener("activate", function(event) { - console.log("[PWA Builder] Claiming clients for current page"); - event.waitUntil(self.clients.claim()); -}); - -// If any fetch fails, it will look for the request in the cache and serve it from there first -self.addEventListener("fetch", function(event) { - if (event.request.method !== "GET") return; - - if (comparePaths(event.request.url, networkFirstPaths)) { - networkFirstFetch(event); - } else { - cacheFirstFetch(event); - } + event.waitUntil(preLoad()); + console.log("installed latest version"); }); -function cacheFirstFetch(event) { - event.respondWith( - fromCache(event.request).then( - function(response) { - // The response was found in the cache so we responde with it and update the entry - - // This is where we call the server to get the newest version of the - // file to use the next time we show view - event.waitUntil( - fetch(event.request).then(function(response) { - return updateCache(event.request, response); - }), - ); - - return response; - }, - function() { - // The response was not found in the cache so we look for it on the server - return fetch(event.request) - .then(function(response) { - // If request was success, add or update it in the cache - event.waitUntil(updateCache(event.request, response.clone())); - - return response; - }) - .catch(function(error) { - // The following validates that the request was for a navigation to a new document - if (event.request.destination !== "document" || event.request.mode !== "navigate") { - return; - } - - console.log("[PWA Builder] Network request failed and no cache." + error); - // Use the precached offline page as fallback - return caches.open(CACHE).then(function(cache) { - cache.match(offlineFallbackPage); - }); - }); - }, - ), - ); -} - -function networkFirstFetch(event) { - event.respondWith( - fetch(event.request) - .then(function(response) { - // If request was success, add or update it in the cache - event.waitUntil(updateCache(event.request, response.clone())); - return response; - }) - .catch(function(error) { - console.log("[PWA Builder] Network request Failed. Serving content from cache: " + error); - return fromCache(event.request); - }), - ); -} - -function fromCache(request) { - // Check to see if you have it in the cache - // Return response - // If not in the cache, then return error page - return caches.open(CACHE).then(function(cache) { - return cache.match(request).then(function(matching) { - if (!matching || matching.status === 404) { - return Promise.reject("no-match"); +const makeNetWorkRequest = request => + new Promise(async (resolve, reject) => { + try { + const networkFetchResponse = await fetch(request); + if (networkFetchResponse.status !== 404) { + resolve(networkFetchResponse); + } else { + throw new Error("no resource found"); } - - return matching; - }); + } catch (error) { + console.error(error); + reject(error); + } }); -} - -function updateCache(request, response) { - if (!comparePaths(request.url, avoidCachingPaths)) { - return caches.open(CACHE).then(function(cache) { - return cache.put(request, response); - }); +const returnFromCache = async request => { + try { + const cache = await caches.open(CACHE_NAME); + const cacheItemMatchingNetworkRequest = await cache.match(request); + if (!cacheItemMatchingNetworkRequest || cacheItemMatchingNetworkRequest.status == 404) { + return cache.match("/"); + } else { + return cacheItemMatchingNetworkRequest; + } + } catch (error) { + console.error(error); } - - return Promise.resolve(); -} +}; +self.addEventListener(FETCH, event => { + event.respondWith( + makeNetWorkRequest(event.request).catch(() => { + return returnFromCache(event.request); + }), + ); +}); // This is an event that can be fired from your page to tell the SW to update the offline page self.addEventListener("refreshOffline", function() { diff --git a/src/app.ts b/src/app.ts index 678fdb1..ff1559b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -42,7 +42,6 @@ app.use(express.static(path.join(__dirname, "../public"))); app.use(express.json()); app.use(express.urlencoded({extended: true})); -const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour app.use( session({ name: process.env.SESSION_NAME, @@ -50,9 +49,6 @@ app.use( resave: false, saveUninitialized: false, store: new MongoStore({mongooseConnection: mongoose.connection}), - cookie: { - expires: expiryDate, - }, }), ); @@ -78,14 +74,6 @@ app.use("/auth", authRouter); app.get("*", function(req: express.Request, res: express.Response) { return res.status(404).redirect("/404"); }); -// 500 - Any server error -app.use(function(err: any, req: express.Request, res: express.Response, next: express.NextFunction) { - res.status(err.status || 500); - res.render("error", { - message: err.message, - error: {}, - }); -}); if (app.get("env") === "development") { app.use(errorHandler());