I managed to register a service worker on my website(currently only localhost, using a self signed cert and have imported into Trusted Certificates in Chrome 62.0.3202.75). Now my problem is that it fails caching some files, presumably because it's making CORS-requests even though in my 'urlsToCache' list there are only local urls(although in some css files I'm importing from google-fonts).
I've tried foreignFetch, but this also fails... I think I've tried nearly anything there is on the internet, but can't find a solution.
My service worker code:
var CACHE_NAME = "stupla-cache-0001";
var urlsToCache = [
'./',
'/sw.js',
'/favicon.ico',
'/stupla-icon-4x.ico',
'/manifest.json',
'/js/bootstrap.min.js',
'/js/custom.js',
'/js/jquery.dlmenu.js',
'/js/jquery.js',
'/js/jquery.smooth-scroll.min.js',
'/js/modernizr.custom.js',
'/js/wow.min.js',
'/color/default.css',
'/css/animate.css',
'/css/bootstrap.min.css',
'/css/dlmenu.css',
'/css/font-awesome.min.css',
'/css/overwrite.css',
'/css/preloader.css',
'/css/style.css',
'/css/table.css',
'/img/mail.png',
'/img/bg-mac.png',
'/img/icons/stupla-icon-2x.ico',
'/img/icons/stupla-icon-4x.ico'];
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil( // !!! Line 31 !!!
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(resp) {
return resp || fetch(event.request).then(function(response) {
console.log(response.urlurl + ": " + response.type);
caches.open(CACHE_NAME).then(function(cache) {
cache.put(event.request, response.clone());
});
return response;
});
}).catch(function() {
return caches.match('/null.dat');
})
);
});
Chrome console output:
Uncaught (in promise) TypeError: Failed to fetch
Promise rejected (async)
(anonymous) # sw.js:31
Related
I'm writing a bible webpage, and I want to use a service worker.
I've got the following code in my service-worker.js:
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
'/',
'/verse/_verse.js',
'/verse/_verse.css',
'/home/_home.js',
'/home/_home.css',
'/bookmarks/_bookmarks.js',
'/bookmarks/_bookmarks.css',
'/search/_search.js',
'/search/_search.css'
];
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
console.log("found response")
console.log(event.request.url)
return response;
}
return fetch(event.request).then(
function(response) {
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have two streams.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
Which is mostly code just taken from the google service worker introduction. However It seems to be only caching the images, css, js and font files - but I'd like it to cache the HTML of a page as well, to make it truly available offline.
All my content on my site is routed through to index.php and served from there, based off the REQUEST_URI. How can I modify the service worker code to save the HTML of a URI request and serve it back in case its offline?
I'm pretty new to react and I'm trying to implement a service worker at the moment.
Actually I always get an error 'Uncaught SyntaxError: Unexpected token 'export'' in my "serviceworker.js" class.
Here's my main.tsx file.
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import App from './app/app';
import * as registerServiceWorker from './serviceworker/serviceworker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker.register();
And thats my "serviceworker.js" file.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
)
export function register(config) {
if ('serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
// const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
// if (publicUrl.origin !== window.location.origin) {
// // Our service worker won't work if PUBLIC_URL is on a different origin
// // from what our page is served on. This might happen if a CDN is used to
//
// return;
// }
window.addEventListener('load', () => {
const swUrl = `/serviceworker/serviceworker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, '
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See /CRA-PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType === null)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
Any idea what I did wrong here?
I already added Babel as suggested in this thread react export Unexpected token but the error didn't disappear.
I already tried to export it via modules.export, but no sucess either.
Thanks in advance!
EDIT:
Thats what my ".babelrc" looks like:
{
"presets": ["#babel/preset-react"],
"plugins": [
"babel-plugin-transform-export-extensions",
"transform-es2015-modules-commonjs"
]
}
Thats what my ".babelrc" looks like:
{
"presets": ["#babel/preset-react"],
"plugins": [
"babel-plugin-transform-export-extensions",
"transform-es2015-modules-commonjs"
]
}
This problem occurs because you are trying to use the same file as the service worker you are registering it with. Because of this, the browser cannot figure out which service worker features you need.
Use for example this content for service-worker.js in your public folder:
self.addEventListener('push', (event) => {
const data = event.data.json();
console.log('New notification', data);
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.description,
icon: data.icon,
})
);
});
I would like to use a service worker to cache files and improve user experience by providing offline pages. I used the pwabuilder.com to create the files for the website. Unfortunately, even when using the code without any elements to cache it issues the error "Uncaught (in promise) TypeError: Request failed"
I double checked the code, I tried the different bug fixes shown on Google Developper and Stackoverflow, but none of these helped me fix the issue.
I have this in the HTML file:
if ("serviceWorker" in navigator) {
if (navigator.serviceWorker.controller) {
console.log("[PWA Builder] active service worker found, no need to register");
} else {
// Register the service worker
navigator.serviceWorker
.register("pwabuilder-sw.js", {
scope: "./"
})
.then(function (reg) {
console.log("[PWA Builder] Service worker has been registered for scope: " + reg.scope);
});
}
}
The service worker registers sucessfully.
The pwabuilder-sw.js is this one:
//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 */
'/cms/stylesheets/bootstrap.css',
'/cms/stylesheets/ifpayroll.css',
'/cms/stylesheets/animate.css',
'/cms/stylesheets/fontawesome-webfont.css',
'/cms/javascript/main.js',
'/cms/javascript/aos.js',
'/cms/images/logo#3x.png',
];
// 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\/.*/
];
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;
}
}
}
return false;
}
self.addEventListener("install", function (event) {
console.log("[PWA Builder] Install Event processing");
console.log("[PWA Builder] Skip waiting on install");
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);
}
});
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");
}
return matching;
});
});
}
function updateCache(request, response) {
if (!comparePaths(request.url, avoidCachingPaths)) {
return caches.open(CACHE).then(function (cache) {
return cache.put(request, response);
});
}
return Promise.resolve();
}
It is 100% the same as the one provided on pwabuilder.com except for the cached files that have been added.
Manifest: unknown 'orientation' value ignored.
pwabuilder-sw.js:83 [PWA Builder] Install Event processing
pwabuilder-sw.js:87 [PWA Builder] Skip waiting on install
pwabuilder-sw.js:97 [PWA Builder] Caching pages during install
legal.html:63 [PWA] Service worker has been registered for scope: https://www.ifpayroll.lu/
pwabuilder-sw.js:1 Uncaught (in promise) TypeError: Request failed
This is what I get.
You have to change this line to reflect your real filename, and make sure that file exists:
const offlineFallbackPage = "ToDo-replace-this-name.html";
Then you can also delete these lines:
if (offlineFallbackPage === "ToDo-replace-this-name.html") {
return cache.add(new Response("TODO: Update the value of the offlineFallbackPage constant in the serviceworker."));
}
The offline fallback page instruction is badly documented IMO/annoying.
These lines can be removed:
if (offlineFallbackPage === "ToDo-replace-this-name.html") {
return cache.add(new Response("TODO: Update the value of the offlineFallbackPage constant in the serviceworker."));
}
I am basically caching an offline page and loading it when my website is offline.
For this I have created a page say 'signIn' and the javascript file of 'SignIn' is javascript->pages->signIn here I have initiated the service worker like
javascript/page/script.js
if('serviceWorker' in navigator){
navigator.serviceWorker.register('./sw1.js').then(function(reg){
console.log("Service workers registered");
});
}
else{
console.log("Browser doesnt support service workers");
}
})
The sw1.js and the offline.html is basically in the same folder as the page SignIn.
self.addEventListener('install', function(event) {
var offlineRequest = new Request('./offline.html');
event.waitUntil(
fetch(offlineRequest).then(function(response) {
return caches.open('offline').then(function(cache) {
console.log('[oninstall] Cached offline page', response.url);
return cache.put(offlineRequest, response);
});
})
);
});
self.addEventListener('fetch', function(event) {
var request = event.request;
if (request.method === 'GET') {
console.log(request);
event.respondWith(
fetch(request).then(function(response){
console.log("From Network "+response);
return response;
}).catch(function(error) {
console.log(
'[onfetch] Failed. Serving cached offline fallback ' +
error
);
return caches.open('offline').then(function(cache) {
console.log("Opened Cache");
return cache.match('./offline.html');
});
})
);
}
});
Basically things work fine when I am online but When i am offline I get the following error in chrome-dev-tools-applications .
Please Help me.
Hello there guys im new to this technology and i would like to ask for help for my code. What im trying to do is to cache assets files and have returned from service worker.
This is the code im using to register the service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js')
.then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
And this is the code inside service worker
importScripts('/cache-poli.js');
var CACHE_VERSION = 'app-v2';
var CACHE_FILES = [
'/',
'/js/plugins/bootstrap/js/bootstrap.min.js',
'/js/plugins/bootstrap-select/bootstrap-select.min.js',
'/js/plugins/prettyphoto/js/jquery.prettyPhoto.js',
'/js/plugins/jquery.sticky.min.js',
'/js/plugins/jquery.easing.min.js',
'/js/plugins/animate/js/animate.js',
'/js/jquery.fancybox.js',
'/js/plugins/jquery/jquery-ui-1.11.1.min.js',
'/js/jquery.scrollbar.min.js',
'/js/plugins/owlcarousel2/owl.carousel.min.js',
'/js/plugins/elevateZoom/jquery.elevateZoom-3.0.8.min.js',
'/js/theme.js',
'/js/cmsfuncs.js',
'/js/theme-config.js',
'/js/jquery.mCustomScrollbar.concat.min.js',
'/js/plugins/jquery/jquery-2.1.4.min.js',
'/js/jquery.cookie.js',
'/js/plugins/bootstrap/css/bootstrap.min.css',
'/fonts/fontawesome/css/font-awesome.min.css',
'/fonts/webfont/css/simple-line-icons.css',
'/fonts/elegantfont/css/elegantfont.css',
'/js/plugins/bootstrap-select/bootstrap-select.min.css',
'/js/plugins/owlcarousel2/assets/owl.carousel.min.css',
'/js/plugins/prettyphoto/css/prettyPhoto.css',
'/js/plugins/animate/css/animate.css',
'/s/plugins/accordion/css/magicaccordion.css',
'/css/jquery.scrollbar.css',
'/css/megamenu.css',
'/css/theme.css',
'/css/slider/slide.css',
'/css/jquery.mCustomScrollbar.css',
'/css/responsive.css',
'/css/theme.css'
];
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(CACHE_VERSION)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(CACHE_FILES);
})
);
});
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function(keys){
return Promise.all(keys.map(function(key, i){
if(key !== CACHE_VERSION){
return caches.delete(keys[i]);
}
}))
})
)
});
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open(CACHE_VERSION).then(function(cache){
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
})
)
});
Im using google chrome dev tools to see the installation proccess everything is cached as it should and the service worker shows no errors but when im trying to access the website again it gives me an error.
This site can’t be reached
The webpage at domain.com might be temporarily down or it may have moved permanently to a new web address.
I too had the same error.
Actually, the problem is quite self-explanatory. What the browser is telling is that the path you are trying to reach is not reachable.
In your code, it looks like you have cached the root '/'. I assume you were facing this problem when you were trying to access some other path like '/somepath'.
Because you haven't cached those , you were getting this error.
So in your array if you also add :
var CACHE_FILES = ['/',
'/somepath', ...];
The error won't occur.
I used the exact same method and the error was gone.