Skip to content

Commit f0ffd1f

Browse files
johnnyreillyskipjack
authored andcommitted
docs(guides): add pwa guide (#1737)
Add `progressive-web-application.md` guide which documents how to use the `workbox-webpack-plugin` to build an offline app. More on PWAs in webpack can be added here by future contributors. Resolves #1145
1 parent 7018c23 commit f0ffd1f

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
title: Progressive Web Application
3+
sort: 14
4+
contributors:
5+
- johnnyreilly
6+
---
7+
8+
T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide.
9+
10+
Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/).
11+
12+
This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup.
13+
14+
15+
## We Don't Work Offline Now
16+
17+
So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files).
18+
19+
So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script:
20+
21+
__package.json__
22+
23+
``` diff
24+
{
25+
...
26+
"scripts": {
27+
- "build": "webpack"
28+
+ "build": "webpack",
29+
+ "start": "http-server dist"
30+
},
31+
...
32+
}
33+
```
34+
35+
If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output:
36+
37+
``` bash
38+
> http-server dist
39+
40+
Starting up http-server, serving dist
41+
Available on:
42+
http://xx.x.x.x:8080
43+
http://127.0.0.1:8080
44+
http://xxx.xxx.x.x:8080
45+
Hit CTRL-C to stop the server
46+
```
47+
48+
If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served up from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available.
49+
50+
This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application.
51+
52+
53+
## Adding Workbox
54+
55+
Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file:
56+
57+
``` bash
58+
npm install workbox-webpack-plugin --save-dev
59+
```
60+
61+
__webpack.config.js__
62+
63+
``` diff
64+
const path = require('path');
65+
const HtmlWebpackPlugin = require('html-webpack-plugin');
66+
const CleanWebpackPlugin = require('clean-webpack-plugin');
67+
+ const WorkboxPlugin = require('workbox-webpack-plugin');
68+
69+
module.exports = {
70+
entry: {
71+
app: './src/index.js',
72+
print: './src/print.js'
73+
},
74+
plugins: [
75+
new CleanWebpackPlugin(['dist']),
76+
new HtmlWebpackPlugin({
77+
- title: 'Output Management'
78+
+ title: 'Progressive Web Application'
79+
- })
80+
+ }),
81+
+ new WorkboxPlugin({
82+
+ // these options encourage the ServiceWorkers to get in there fast
83+
+ // and not allow any straggling "old" SWs to hang around
84+
+ clientsClaim: true,
85+
+ skipWaiting: true
86+
+ })
87+
],
88+
output: {
89+
filename: '[name].bundle.js',
90+
path: path.resolve(__dirname, 'dist')
91+
}
92+
};
93+
```
94+
95+
With that in place, let's see what happens when we do an `npm run build`:
96+
97+
``` bash
98+
clean-webpack-plugin: /mnt/c/Source/webpack-follow-along/dist has been removed.
99+
Hash: 6588e31715d9be04be25
100+
Version: webpack 3.10.0
101+
Time: 782ms
102+
Asset Size Chunks Chunk Names
103+
app.bundle.js 545 kB 0, 1 [emitted] [big] app
104+
print.bundle.js 2.74 kB 1 [emitted] print
105+
index.html 254 bytes [emitted]
106+
precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted]
107+
sw.js 1 kB [emitted]
108+
[0] ./src/print.js 87 bytes {0} {1} [built]
109+
[1] ./src/index.js 477 bytes {0} [built]
110+
[3] (webpack)/buildin/global.js 509 bytes {0} [built]
111+
[4] (webpack)/buildin/module.js 517 bytes {0} [built]
112+
+ 1 hidden module
113+
Child html-webpack-plugin for "index.html":
114+
1 asset
115+
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
116+
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
117+
+ 2 hidden modules
118+
```
119+
120+
As you can see, we now have 2 extra files being generated; `sw.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `sw.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `sw.js` requires so it can run. Your own generated files will likely be different; but you should have an `sw.js` file there.
121+
122+
So we're now at the happy point of having produced a Service Worker. What's next?
123+
124+
125+
## Registering Our Service Worker
126+
127+
Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below:
128+
129+
__index.js__
130+
131+
``` diff
132+
import _ from 'lodash';
133+
import printMe from './print.js';
134+
135+
+ if ('serviceWorker' in navigator) {
136+
+ window.addEventListener('load', () => {
137+
+ navigator.serviceWorker.register('/sw.js').then(registration => {
138+
+ console.log('SW registered: ', registration);
139+
+ }).catch(registrationError => {
140+
+ console.log('SW registration failed: ', registrationError);
141+
+ });
142+
+ });
143+
+ }
144+
```
145+
146+
Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see:
147+
148+
``` bash
149+
SW registered
150+
```
151+
152+
Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server.
153+
154+
155+
## Conclusion
156+
157+
You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/).

0 commit comments

Comments
 (0)