Commit | Line | Data |
---|---|---|
05b9ad64 JC |
1 | // This optional code is used to register a service worker. |
2 | // register() is not called by default. | |
3 | ||
4 | // This lets the app load faster on subsequent visits in production, and gives | |
5 | // it offline capabilities. However, it also means that developers (and users) | |
6 | // will only see deployed updates on subsequent visits to a page, after all the | |
7 | // existing tabs open on the page have been closed, since previously cached | |
8 | // resources are updated in the background. | |
9 | ||
10 | // To learn more about the benefits of this model and instructions on how to | |
11 | // opt-in, read https://bit.ly/CRA-PWA | |
12 | ||
13 | const isLocalhost = Boolean( | |
14 | window.location.hostname === 'localhost' || | |
15 | // [::1] is the IPv6 localhost address. | |
16 | window.location.hostname === '[::1]' || | |
17 | // 127.0.0.0/8 are considered localhost for IPv4. | |
18 | window.location.hostname.match( | |
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ | |
20 | ) | |
21 | ); | |
22 | ||
23 | export function register(config) { | |
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { | |
25 | // The URL constructor is available in all browsers that support SW. | |
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); | |
27 | if (publicUrl.origin !== window.location.origin) { | |
28 | // Our service worker won't work if PUBLIC_URL is on a different origin | |
29 | // from what our page is served on. This might happen if a CDN is used to | |
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 | |
31 | return; | |
32 | } | |
33 | ||
34 | window.addEventListener('load', () => { | |
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; | |
36 | ||
37 | if (isLocalhost) { | |
38 | // This is running on localhost. Let's check if a service worker still exists or not. | |
39 | checkValidServiceWorker(swUrl, config); | |
40 | ||
41 | // Add some additional logging to localhost, pointing developers to the | |
42 | // service worker/PWA documentation. | |
43 | navigator.serviceWorker.ready.then(() => { | |
44 | console.log( | |
45 | 'This web app is being served cache-first by a service ' + | |
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' | |
47 | ); | |
48 | }); | |
49 | } else { | |
50 | // Is not localhost. Just register service worker | |
51 | registerValidSW(swUrl, config); | |
52 | } | |
53 | }); | |
54 | } | |
55 | } | |
56 | ||
57 | function registerValidSW(swUrl, config) { | |
58 | navigator.serviceWorker | |
59 | .register(swUrl) | |
60 | .then(registration => { | |
61 | registration.onupdatefound = () => { | |
62 | const installingWorker = registration.installing; | |
63 | if (installingWorker == null) { | |
64 | return; | |
65 | } | |
66 | installingWorker.onstatechange = () => { | |
67 | if (installingWorker.state === 'installed') { | |
68 | if (navigator.serviceWorker.controller) { | |
69 | // At this point, the updated precached content has been fetched, | |
70 | // but the previous service worker will still serve the older | |
71 | // content until all client tabs are closed. | |
72 | console.log( | |
73 | 'New content is available and will be used when all ' + | |
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' | |
75 | ); | |
76 | ||
77 | // Execute callback | |
78 | if (config && config.onUpdate) { | |
79 | config.onUpdate(registration); | |
80 | } | |
81 | } else { | |
82 | // At this point, everything has been precached. | |
83 | // It's the perfect time to display a | |
84 | // "Content is cached for offline use." message. | |
85 | console.log('Content is cached for offline use.'); | |
86 | ||
87 | // Execute callback | |
88 | if (config && config.onSuccess) { | |
89 | config.onSuccess(registration); | |
90 | } | |
91 | } | |
92 | } | |
93 | }; | |
94 | }; | |
95 | }) | |
96 | .catch(error => { | |
97 | console.error('Error during service worker registration:', error); | |
98 | }); | |
99 | } | |
100 | ||
101 | function checkValidServiceWorker(swUrl, config) { | |
102 | // Check if the service worker can be found. If it can't reload the page. | |
103 | fetch(swUrl, { | |
104 | headers: { 'Service-Worker': 'script' }, | |
105 | }) | |
106 | .then(response => { | |
107 | // Ensure service worker exists, and that we really are getting a JS file. | |
108 | const contentType = response.headers.get('content-type'); | |
109 | if ( | |
110 | response.status === 404 || | |
111 | (contentType != null && contentType.indexOf('javascript') === -1) | |
112 | ) { | |
113 | // No service worker found. Probably a different app. Reload the page. | |
114 | navigator.serviceWorker.ready.then(registration => { | |
115 | registration.unregister().then(() => { | |
116 | window.location.reload(); | |
117 | }); | |
118 | }); | |
119 | } else { | |
120 | // Service worker found. Proceed as normal. | |
121 | registerValidSW(swUrl, config); | |
122 | } | |
123 | }) | |
124 | .catch(() => { | |
125 | console.log( | |
126 | 'No internet connection found. App is running in offline mode.' | |
127 | ); | |
128 | }); | |
129 | } | |
130 | ||
131 | export function unregister() { | |
132 | if ('serviceWorker' in navigator) { | |
133 | navigator.serviceWorker.ready | |
134 | .then(registration => { | |
135 | registration.unregister(); | |
136 | }) | |
137 | .catch(error => { | |
138 | console.error(error.message); | |
139 | }); | |
140 | } | |
141 | } |