Skip to content

Commit 75088ab

Browse files
committed
Documentation + a few SW tweaks.
1 parent 8289386 commit 75088ab

File tree

6 files changed

+98
-8
lines changed

6 files changed

+98
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ Please refer to the [User Guide](https://github.com/facebookincubator/create-rea
151151
* Import CSS and image files directly from JavaScript.
152152
* Autoprefixed CSS, so you don’t need `-webkit` or other prefixes.
153153
* A `build` script to bundle JS, CSS, and images for production, with sourcemaps.
154+
* An offline-first [service worker](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers) and a [web app manifest](https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/), meeting all the [Progressive Web App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) criteria.
154155

155156
**The feature set is intentionally limited**. It doesn’t support advanced features such as server rendering or CSS modules. The tool is also **non-configurable** because it is hard to provide a cohesive experience and easy updates across a set of tools when the user can tweak anything.
156157

packages/react-scripts/config/webpack.config.prod.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ module.exports = {
278278
new SWPrecacheWebpackPlugin({
279279
dontCacheBustUrlsMatching: /\.\w{8}\./,
280280
filename: 'service-worker.js',
281+
navigateFallback: publicUrl + '/index.html',
281282
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/]
282283
})
283284
],

packages/react-scripts/template/README.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,60 @@ Learn more about React Storybook:
10481048

10491049
## Making a Progressive Web App
10501050

1051-
You can turn your React app into a [Progressive Web App](https://developers.google.com/web/progressive-web-apps/) by following the steps in [this repository](https://github.com/jeffposnick/create-react-pwa).
1051+
By default, the production build is a fully functional, offline-first
1052+
[Progressive Web App](https://developers.google.com/web/progressive-web-apps/).
1053+
1054+
The [`sw-precache-webpack-plugin`](https://github.com/goldhand/sw-precache-webpack-plugin)
1055+
is integrated into [`webpack.config.prod.js`](../config/webpack.config.prod.js),
1056+
and it will take care of generating a service worker file that will automatically
1057+
precache all of your local assets and keep them up to date as you deploy updates.
1058+
The service worker will use a [cache-first strategy](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network)
1059+
for handling all requests for local assets, including the initial HTML, ensuring
1060+
that you web app is reliably fast, even on a slow or unreliable network.
1061+
1062+
It includes a [web app manifest](https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/),
1063+
located at [`public/manifest.json`](public/manifest.json), that you might want
1064+
to customize with metadata specific to your web application, such as its name
1065+
and branding colors.
1066+
1067+
### Offline-First Considerations
1068+
1069+
1. The service worker is only enabled in the production environment. It's
1070+
recommended that you do not enable an offline-first service worker in a
1071+
development environment, as it can lead to frustration when previously cached
1072+
assets are used and do not include the latest changes you've made locally.
1073+
1074+
1. If possible,configure your production environment to serve the generated
1075+
`service-worker.js` [with HTTP caching disabled](http://stackoverflow.com/questions/38843970/service-worker-javascript-update-frequency-every-24-hours).
1076+
If that's not possible—[GitHub Pages](#github-pages), for instance, does not
1077+
allow you to change the default 10 minute HTTP cache lifetime—then be aware
1078+
that if you visit your production site, and then revisit again before
1079+
`service-worker.js` has expired from your HTTP cache, you'll continue to get
1080+
the previously cached assets from the service worker. If you have an immediate
1081+
need to view your updated production deployment, performing a shift-refresh
1082+
will temporarily disable the service worker and retrieve all assets from the
1083+
network.
1084+
1085+
1. Users aren't always familiar with offline-first web apps. It can be useful to
1086+
let the user know when the service worker has finished populating your caches
1087+
(showing a "This web app works offline!" message) and also let them know when
1088+
the service worker has fetched the latest updates that will be available the
1089+
next time they load the page (showing a "New content is available; please
1090+
refresh." message). Showing this messages is currently left as an exercise to
1091+
the developer, but as a starting point, you can make use of the logic included
1092+
in [`src/register-service-worker.js`](src/register-service-worker.js), which
1093+
demonstrates which service worker lifecycle events to listen for to detect each
1094+
scenario, and which as a default, just logs appropriate messages to the
1095+
JavaScript console.
1096+
1097+
1. By default, the generated service worker file will not intercept or cache any
1098+
cross-origin traffic, like HTTP [API requests](#integrating-with-an-api-backend),
1099+
images, or embeds loaded from a different domain. If you would like to use a
1100+
runtime caching strategy for those requests, you can [`eject`](#npm-run-eject)
1101+
and then configure the
1102+
[`runtimeCaching`](https://github.com/GoogleChrome/sw-precache#runtimecaching-arrayobject)
1103+
option in the `SWPrecachePlugin` section of
1104+
[`webpack.config.prod.js`](../config/webpack.config.prod.js).
10521105

10531106
## Deployment
10541107

@@ -1096,6 +1149,15 @@ This is because when there is a fresh page load for a `/todos/42`, the server lo
10961149

10971150
Now requests to `/todos/42` will be handled correctly both in development and in production.
10981151

1152+
On a production build, and in a browser that supports [service workers](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers),
1153+
the service worker will automatically handle all navigation requests, like for
1154+
`/todos/42`, by serving the cached copy of your `index.html`. This
1155+
service worker navigation routing can be configured or disabled by
1156+
[`eject`ing](#npm-run-eject) and then modifying the
1157+
[`navigateFallback`](https://github.com/GoogleChrome/sw-precache#navigatefallback-string)
1158+
and [`navigateFallbackWhitelist`](https://github.com/GoogleChrome/sw-precache#navigatefallbackwhitelist-arrayregexp)
1159+
options of the `SWPreachePlugin` [configuration](../config/webpack.config.prod.js).
1160+
10991161
### Building for Relative Paths
11001162

11011163
By default, Create React App produces a build assuming your app is hosted at the server root.<br>

packages/react-scripts/template/public/index.html

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,5 @@
2828
To begin the development, run `npm start`.
2929
To create a production bundle, use `npm run build`.
3030
-->
31-
<script>
32-
if ('%NODE_ENV%' === 'production' && 'serviceWorker' in navigator) {
33-
window.addEventListener('load', function() {
34-
navigator.serviceWorker.register('%PUBLIC_URL%/service-worker.js');
35-
});
36-
}
37-
</script>
3831
</body>
3932
</html>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
33
import App from './App';
4+
import registerServiceWorker from './register-service-worker';
45
import './index.css';
56

67
ReactDOM.render(
78
<App />,
89
document.getElementById('root')
910
);
11+
12+
registerServiceWorker();
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export default () => {
2+
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
3+
window.addEventListener('load', () => {
4+
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
5+
navigator.serviceWorker.register(swUrl).then(registration => {
6+
registration.onupdatefound = () => {
7+
const installingWorker = registration.installing;
8+
installingWorker.onstatechange = () => {
9+
if (installingWorker.state === 'installed') {
10+
if (navigator.serviceWorker.controller) {
11+
// At this point, the old content will have been purged and
12+
// the fresh content will have been added to the cache.
13+
// It's the perfect time to display a "New content is
14+
// available; please refresh." message in your web app.
15+
console.log('New content is available; please refresh.');
16+
} else {
17+
// At this point, everything has been precached.
18+
// It's the perfect time to display a
19+
// "Content is cached for offline use." message.
20+
console.log('Content is cached for offline use.');
21+
}
22+
}
23+
};
24+
};
25+
}).catch(error => {
26+
console.error('Error during service worker registration:', error);
27+
});
28+
});
29+
}
30+
};

0 commit comments

Comments
 (0)