Skip to content

Commit a7398e9

Browse files
committed
Restore service worker
1 parent 0370a6e commit a7398e9

5 files changed

Lines changed: 247 additions & 128 deletions

File tree

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
"react-router": "^5.2.0",
1414
"react-router-dom": "^5.2.0",
1515
"react-scripts": "^5.0.1",
16-
"uuid": "^10.0.0"
16+
"uuid": "^10.0.0",
17+
"workbox-core": "^7.1.0",
18+
"workbox-expiration": "^7.1.0",
19+
"workbox-precaching": "^7.1.0",
20+
"workbox-routing": "^7.1.0",
21+
"workbox-strategies": "^7.1.0"
1722
},
1823
"scripts": {
1924
"dev": "craco start",

src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React from "react";
22
import { createRoot } from "react-dom/client";
33
import App from "./App";
4-
// import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
4+
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
55

66
const container = document.getElementById("root");
77
const root = createRoot(container);
88
root.render(<App />);
9+
10+
serviceWorkerRegistration.register();

src/service-worker.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* eslint-disable no-restricted-globals */
2+
/* eslint-disable no-param-reassign */
3+
/* eslint-disable no-console */
4+
/* eslint-disable no-use-before-define */
5+
6+
// This service worker can be customized!
7+
// See https://developers.google.com/web/tools/workbox/modules
8+
// for the list of available Workbox modules, or add any other
9+
// code you'd like.
10+
// You can also remove this file if you'd prefer not to use a
11+
// service worker, and the Workbox build step will be skipped.
12+
13+
import { clientsClaim } from "workbox-core";
14+
import { ExpirationPlugin } from "workbox-expiration";
15+
import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching";
16+
import { registerRoute } from "workbox-routing";
17+
import { StaleWhileRevalidate } from "workbox-strategies";
18+
19+
clientsClaim();
20+
21+
// Precache all of the assets generated by your build process.
22+
// Their URLs are injected into the manifest variable below.
23+
// This variable must be present somewhere in your service worker file,
24+
// even if you decide not to use precaching. See https://cra.link/PWA
25+
/* eslint-disable no-underscore-dangle */
26+
precacheAndRoute(self.__WB_MANIFEST);
27+
28+
// Set up App Shell-style routing, so that all navigation requests
29+
// are fulfilled with your index.html shell. Learn more at
30+
// https://developers.google.com/web/fundamentals/architecture/app-shell
31+
const fileExtensionRegexp = new RegExp("/[^/?]+\\.[^/]+$");
32+
registerRoute(
33+
// Return false to exempt requests from being fulfilled by index.html.
34+
({ request, url }) => {
35+
// If this isn't a navigation, skip.
36+
if (request.mode !== "navigate") {
37+
return false;
38+
} // If this is a URL that starts with /_, skip.
39+
40+
if (url.pathname.startsWith("/_")) {
41+
return false;
42+
} // If this looks like a URL for a resource, because it contains // a file extension, skip.
43+
44+
if (url.pathname.match(fileExtensionRegexp)) {
45+
return false;
46+
} // Return true to signal that we want to use the handler.
47+
48+
return true;
49+
},
50+
createHandlerBoundToURL(`${process.env.PUBLIC_URL}/index.html`),
51+
);
52+
53+
// An example runtime caching route for requests that aren't handled by the
54+
// precache, in this case same-origin .png requests like those from in public/
55+
registerRoute(
56+
// Add in any other file extensions or routing criteria as needed.
57+
({ url }) => url.origin === self.location.origin && url.pathname.endsWith(".png"), // Customize this strategy as needed, e.g., by changing to CacheFirst.
58+
new StaleWhileRevalidate({
59+
cacheName: "images",
60+
plugins: [
61+
// Ensure that once this runtime cache reaches a maximum size the
62+
// least-recently used images are removed.
63+
new ExpirationPlugin({ maxEntries: 50 }),
64+
],
65+
}),
66+
);
67+
68+
// This allows the web app to trigger skipWaiting via
69+
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
70+
self.addEventListener("message", (event) => {
71+
if (event.data && event.data.type === "SKIP_WAITING") {
72+
self.skipWaiting();
73+
}
74+
});
75+
76+
// Any other custom service worker logic can go here.

src/serviceWorkerRegistration.js

Lines changed: 126 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,138 @@
1-
// /* eslint-disable */
2-
// // This optional code is used to register a service worker.
3-
// // register() is not called by default.
1+
/* eslint-disable */
2+
// This optional code is used to register a service worker.
3+
// register() is not called by default.
44

5-
// // This lets the app load faster on subsequent visits in production, and gives
6-
// // it offline capabilities. However, it also means that developers (and users)
7-
// // will only see deployed updates on subsequent visits to a page, after all the
8-
// // existing tabs open on the page have been closed, since previously cached
9-
// // resources are updated in the background.
5+
// This lets the app load faster on subsequent visits in production, and gives
6+
// it offline capabilities. However, it also means that developers (and users)
7+
// will only see deployed updates on subsequent visits to a page, after all the
8+
// existing tabs open on the page have been closed, since previously cached
9+
// resources are updated in the background.
1010

11-
// // To learn more about the benefits of this model and instructions on how to
12-
// // opt-in, read https://cra.link/PWA
11+
// To learn more about the benefits of this model and instructions on how to
12+
// opt-in, read https://cra.link/PWA
1313

14-
// const isLocalhost = Boolean(
15-
// window.location.hostname === 'localhost' ||
16-
// // [::1] is the IPv6 localhost address.
17-
// window.location.hostname === '[::1]' ||
18-
// // 127.0.0.0/8 are considered localhost for IPv4.
19-
// window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
20-
// );
14+
const isLocalhost = Boolean(
15+
window.location.hostname === 'localhost' ||
16+
// [::1] is the IPv6 localhost address.
17+
window.location.hostname === '[::1]' ||
18+
// 127.0.0.0/8 are considered localhost for IPv4.
19+
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
20+
);
2121

22-
// export function register(config) {
23-
// if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
24-
// // The URL constructor is available in all browsers that support SW.
25-
// const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
26-
// if (publicUrl.origin !== window.location.origin) {
27-
// // Our service worker won't work if PUBLIC_URL is on a different origin
28-
// // from what our page is served on. This might happen if a CDN is used to
29-
// // serve assets; see https://github.com/facebook/create-react-app/issues/2374
30-
// return;
31-
// }
22+
export function register(config) {
23+
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
24+
// The URL constructor is available in all browsers that support SW.
25+
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
26+
if (publicUrl.origin !== window.location.origin) {
27+
// Our service worker won't work if PUBLIC_URL is on a different origin
28+
// from what our page is served on. This might happen if a CDN is used to
29+
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
30+
return;
31+
}
3232

33-
// window.addEventListener('load', () => {
34-
// const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
33+
window.addEventListener('load', () => {
34+
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
3535

36-
// if (isLocalhost) {
37-
// // This is running on localhost. Let's check if a service worker still exists or not.
38-
// checkValidServiceWorker(swUrl, config);
36+
if (isLocalhost) {
37+
// This is running on localhost. Let's check if a service worker still exists or not.
38+
checkValidServiceWorker(swUrl, config);
3939

40-
// // Add some additional logging to localhost, pointing developers to the
41-
// // service worker/PWA documentation.
42-
// navigator.serviceWorker.ready.then(() => {
43-
// console.log(
44-
// 'This web app is being served cache-first by a service ' +
45-
// 'worker. To learn more, visit https://cra.link/PWA'
46-
// );
47-
// });
48-
// } else {
49-
// // Is not localhost. Just register service worker
50-
// registerValidSW(swUrl, config);
51-
// }
52-
// });
53-
// }
54-
// }
40+
// Add some additional logging to localhost, pointing developers to the
41+
// service worker/PWA documentation.
42+
navigator.serviceWorker.ready.then(() => {
43+
console.log(
44+
'This web app is being served cache-first by a service ' +
45+
'worker. To learn more, visit https://cra.link/PWA'
46+
);
47+
});
48+
} else {
49+
// Is not localhost. Just register service worker
50+
registerValidSW(swUrl, config);
51+
}
52+
});
53+
}
54+
}
5555

56-
// function registerValidSW(swUrl, config) {
57-
// navigator.serviceWorker
58-
// .register(swUrl)
59-
// .then((registration) => {
60-
// registration.onupdatefound = () => {
61-
// const installingWorker = registration.installing;
62-
// if (installingWorker == null) {
63-
// return;
64-
// }
65-
// installingWorker.onstatechange = () => {
66-
// if (installingWorker.state === 'installed') {
67-
// if (navigator.serviceWorker.controller) {
68-
// // At this point, the updated precached content has been fetched,
69-
// // but the previous service worker will still serve the older
70-
// // content until all client tabs are closed.
71-
// console.log(
72-
// 'New content is available and will be used when all ' +
73-
// 'tabs for this page are closed. See https://cra.link/PWA.'
74-
// );
56+
function registerValidSW(swUrl, config) {
57+
navigator.serviceWorker
58+
.register(swUrl)
59+
.then((registration) => {
60+
registration.onupdatefound = () => {
61+
const installingWorker = registration.installing;
62+
if (installingWorker == null) {
63+
return;
64+
}
65+
installingWorker.onstatechange = () => {
66+
if (installingWorker.state === 'installed') {
67+
if (navigator.serviceWorker.controller) {
68+
// At this point, the updated precached content has been fetched,
69+
// but the previous service worker will still serve the older
70+
// content until all client tabs are closed.
71+
console.log(
72+
'New content is available and will be used when all ' +
73+
'tabs for this page are closed. See https://cra.link/PWA.'
74+
);
7575

76-
// // Execute callback
77-
// if (config && config.onUpdate) {
78-
// config.onUpdate(registration);
79-
// }
80-
// } else {
81-
// // At this point, everything has been precached.
82-
// // It's the perfect time to display a
83-
// // "Content is cached for offline use." message.
84-
// console.log('Content is cached for offline use.');
76+
// Execute callback
77+
if (config && config.onUpdate) {
78+
config.onUpdate(registration);
79+
}
80+
} else {
81+
// At this point, everything has been precached.
82+
// It's the perfect time to display a
83+
// "Content is cached for offline use." message.
84+
console.log('Content is cached for offline use.');
8585

86-
// // Execute callback
87-
// if (config && config.onSuccess) {
88-
// config.onSuccess(registration);
89-
// }
90-
// }
91-
// }
92-
// };
93-
// };
94-
// })
95-
// .catch((error) => {
96-
// console.error('Error during service worker registration:', error);
97-
// });
98-
// }
86+
// Execute callback
87+
if (config && config.onSuccess) {
88+
config.onSuccess(registration);
89+
}
90+
}
91+
}
92+
};
93+
};
94+
})
95+
.catch((error) => {
96+
console.error('Error during service worker registration:', error);
97+
});
98+
}
9999

100-
// function checkValidServiceWorker(swUrl, config) {
101-
// // Check if the service worker can be found. If it can't reload the page.
102-
// fetch(swUrl, {
103-
// headers: { 'Service-Worker': 'script' },
104-
// })
105-
// .then((response) => {
106-
// // Ensure service worker exists, and that we really are getting a JS file.
107-
// const contentType = response.headers.get('content-type');
108-
// if (
109-
// response.status === 404 ||
110-
// (contentType != null && contentType.indexOf('javascript') === -1)
111-
// ) {
112-
// // No service worker found. Probably a different app. Reload the page.
113-
// navigator.serviceWorker.ready.then((registration) => {
114-
// registration.unregister().then(() => {
115-
// window.location.reload();
116-
// });
117-
// });
118-
// } else {
119-
// // Service worker found. Proceed as normal.
120-
// registerValidSW(swUrl, config);
121-
// }
122-
// })
123-
// .catch(() => {
124-
// console.log('No internet connection found. App is running in offline mode.');
125-
// });
126-
// }
100+
function checkValidServiceWorker(swUrl, config) {
101+
// Check if the service worker can be found. If it can't reload the page.
102+
fetch(swUrl, {
103+
headers: { 'Service-Worker': 'script' },
104+
})
105+
.then((response) => {
106+
// Ensure service worker exists, and that we really are getting a JS file.
107+
const contentType = response.headers.get('content-type');
108+
if (
109+
response.status === 404 ||
110+
(contentType != null && contentType.indexOf('javascript') === -1)
111+
) {
112+
// No service worker found. Probably a different app. Reload the page.
113+
navigator.serviceWorker.ready.then((registration) => {
114+
registration.unregister().then(() => {
115+
window.location.reload();
116+
});
117+
});
118+
} else {
119+
// Service worker found. Proceed as normal.
120+
registerValidSW(swUrl, config);
121+
}
122+
})
123+
.catch(() => {
124+
console.log('No internet connection found. App is running in offline mode.');
125+
});
126+
}
127127

128-
// export function unregister() {
129-
// if ('serviceWorker' in navigator) {
130-
// navigator.serviceWorker.ready
131-
// .then((registration) => {
132-
// registration.unregister();
133-
// })
134-
// .catch((error) => {
135-
// console.error(error.message);
136-
// });
137-
// }
138-
// }
128+
export function unregister() {
129+
if ('serviceWorker' in navigator) {
130+
navigator.serviceWorker.ready
131+
.then((registration) => {
132+
registration.unregister();
133+
})
134+
.catch((error) => {
135+
console.error(error.message);
136+
});
137+
}
138+
}

0 commit comments

Comments
 (0)