Skip to content

Commit

Permalink
Merge pull request #211 from labzero/nyscherm/service-worker
Browse files Browse the repository at this point in the history
Add PWA features
  • Loading branch information
JeffreyATW authored May 18, 2018
2 parents 05df402 + 10b247a commit 9602f76
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .babelrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = {
},
},
],
'@babel/preset-stage-2',
["@babel/preset-stage-2", { "decoratorsLegacy": true }],
'@babel/preset-flow',
'@babel/preset-react',
],
Expand Down
3 changes: 3 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ HONEYBADGER_API_KEY=

# SendGrid info for email notifications
SENDGRID_API_KEY=

# Set as true to run https locally, add self-signed certificate in cert folder to trusted certificates
USE_HTTPS=
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ node build/server.js

You can modify `tools/deploy.js` as needed to work with your deployment strategy.

## Service Worker

To run the service worker locally, follow the above steps to run the production server. After testing the service worker, be sure to unregister the service worker in the browser (or close all local Lunch tabs) to avoid issues when testing on the development server.

## Testing

### Unit tests
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@
"webpack-bundle-analyzer": "^2.11.1",
"webpack-dev-middleware": "^3.1.2",
"webpack-hot-middleware": "^2.21.2",
"webpack-node-externals": "^1.7.2"
"webpack-node-externals": "^1.7.2",
"workbox-webpack-plugin": "^3.2.0"
},
"lint-staged": {
"*.{js,jsx}": ["eslint --no-ignore --fix", "git add --force"],
Expand Down
8 changes: 7 additions & 1 deletion public/site.webmanifest
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{
"short_name": "Lunch",
"name": "Lunch",
"description": "A simple lunch voting app for you and your team. Search nearby restaurants, add them to your list, vote for as many as you like, and decide on today’s pick!",
"icons": [
{
"src": "icon.png",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "/"
"start_url": "/",
"display": "standalone",
"theme_color": "#FFC0CB",
"background_color": "#FFF"
}
2 changes: 2 additions & 0 deletions src/components/Html.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Html extends Component {
<meta property="twitter:card" content="summary" />
<meta property="twitter:site" content="labzero" />
<meta property="twitter:image" content={`${root}/tile.png`} />
<meta name="theme-color" content="#FFC0CB" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:400,900" />
{scripts.map(script => (
Expand All @@ -92,6 +93,7 @@ class Html extends Component {
<body>
<div id="app" dangerouslySetInnerHTML={{ __html: children }} />
<script dangerouslySetInnerHTML={{ __html: `window.App=${serialize(app)}` }} />
{!module.hot && <script dangerouslySetInnerHTML={{ __html: `if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js').then(function(registration) {registration.addEventListener('updatefound', () => {window.swUpdate = true; }); }); }); }` }} />}
{apikey && <script src={`https://maps.googleapis.com/maps/api/js?key=${apikey}&libraries=places&v=3`} />}
{scripts.map(script => <script key={script} src={script} />)}
</body>
Expand Down
7 changes: 6 additions & 1 deletion src/components/Link/Link.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ class Link extends React.Component {
}

event.preventDefault();
history.push(this.props.to);

if (window.swUpdate) {
window.location = this.props.to;
} else {
history.push(this.props.to);
}
};

render() {
Expand Down
4 changes: 2 additions & 2 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const accessLogStream = rfs('access.log', {
const app = express();

let internalWsServer;
if (module.hot) {
if (process.env.USE_HTTPS === 'true') {
// use self-signed cert locally
const options = {
key: fs.readFileSync(path.join(__dirname, '../cert/server.key')),
Expand Down Expand Up @@ -442,7 +442,7 @@ app.use(Honeybadger.errorHandler); // Use *after* all other app middleware.
//
// Launch the server
// -----------------------------------------------------------------------------
if (module.hot) {
if (process.env.USE_HTTPS === 'true') {
wsServer.listen(config.wsPort, () => {
/* eslint-disable no-console */
console.log(`The websockets server is running at https://local.lunch.pink:${config.wsPort}/`);
Expand Down
24 changes: 24 additions & 0 deletions src/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* global workbox */
/* eslint-disable no-restricted-globals */

// eslint-disable-next-line no-underscore-dangle
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);

// Cache the index page
workbox.routing.registerRoute(
context => context.url.pathname.indexOf('/api') !== 0 && context.url.pathname.indexOf('/assets') !== 0,
workbox.strategies.cacheFirst({
cacheName: 'pages',
plugins: [
new workbox.expiration.Plugin({
maxAgeSeconds: 30 * 24 * 60 * 60, // 24 hours
}),
],
}),
);

// eslint-disable-next-line no-unused-vars
self.addEventListener('install', event => {
// Activate new service worker as soon as it's installed
self.skipWaiting();
});
10 changes: 8 additions & 2 deletions tools/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import webpack from 'webpack';
import WebpackAssetsManifest from 'webpack-assets-manifest';
import nodeExternals from 'webpack-node-externals';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import {InjectManifest} from 'workbox-webpack-plugin';
import overrideRules from './lib/overrideRules';
import pkg from '../package.json';

Expand Down Expand Up @@ -88,7 +89,7 @@ const config = {
],
// Experimental ECMAScript proposals
// https://babeljs.io/docs/plugins/#presets-stage-x-experimental-presets-
'@babel/preset-stage-2',
["@babel/preset-stage-2", { "decoratorsLegacy": true }],
// Flow
// https://github.com/babel/babel/tree/master/packages/babel-preset-flow
'@babel/preset-flow',
Expand Down Expand Up @@ -368,7 +369,7 @@ const clientConfig = {
),
];
return acc;
}, Object.create(null));
}, Object.create(null));
fs.writeFileSync(chunkFileName, JSON.stringify(chunkFiles, null, 2));
} catch (err) {
console.error(`ERROR: Cannot write ${chunkFileName}: `, err);
Expand All @@ -384,6 +385,11 @@ const clientConfig = {
// https://github.com/th0r/webpack-bundle-analyzer
...(isAnalyze ? [new BundleAnalyzerPlugin()] : []),
]),

new InjectManifest({
swSrc: './src/service-worker.js',
swDest: resolvePath(BUILD_DIR, 'public/service-worker.js'),
}),
],

// Move modules that occur in multiple entry chunks to a new entry chunk (the commons chunk).
Expand Down
157 changes: 153 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2878,6 +2878,12 @@ common-password@^0.1.2:
dependencies:
buffer-crc32 "^0.2.5"

common-tags@^1.4.0:
version "1.7.2"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.7.2.tgz#24d9768c63d253a56ecff93845b44b4df1d52771"
dependencies:
babel-runtime "^6.26.0"

commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
Expand Down Expand Up @@ -5845,6 +5851,12 @@ [email protected]:
version "2.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"

[email protected]:
version "3.1.2"
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.2.tgz#937cf919002077999a73ea8b1951d590e84e01dd"
dependencies:
punycode "2.x.x"

isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
Expand Down Expand Up @@ -6068,6 +6080,14 @@ jest-validate@^22.4.0, jest-validate@^22.4.3:
leven "^2.1.0"
pretty-format "^22.4.3"

joi@^11.1.1:
version "11.4.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-11.4.0.tgz#f674897537b625e9ac3d0b7e1604c828ad913ccb"
dependencies:
hoek "4.x.x"
isemail "3.x.x"
topo "2.x.x"

js-base64@^2.1.8:
version "2.4.1"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.1.tgz#e02813181cd53002888e918935467acb2910e596"
Expand Down Expand Up @@ -6541,6 +6561,10 @@ lodash._isiterateecall@^3.0.0:
version "3.0.9"
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"

lodash._reinterpolate@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"

lodash.assign@^3.0.0, lodash.assign@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa"
Expand Down Expand Up @@ -6699,6 +6723,19 @@ lodash.tail@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"

lodash.template@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
dependencies:
lodash._reinterpolate "~3.0.0"
lodash.templatesettings "^4.0.0"

lodash.templatesettings@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316"
dependencies:
lodash._reinterpolate "~3.0.0"

lodash.toplainobject@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz#28790ad942d293d78aa663a07ecf7f52ca04198d"
Expand Down Expand Up @@ -8702,6 +8739,10 @@ prettier@^1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75"

pretty-bytes@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"

pretty-error@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
Expand Down Expand Up @@ -8834,14 +8875,14 @@ [email protected]:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"

[email protected], punycode@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"

punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"

punycode@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"

puppeteer@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-1.3.0.tgz#f571c5f27153ca164a8188e6328ce2e4946878f3"
Expand Down Expand Up @@ -10957,6 +10998,12 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"

[email protected]:
version "2.0.2"
resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182"
dependencies:
hoek "4.x.x"

toposort-class@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"
Expand Down Expand Up @@ -11620,6 +11667,108 @@ wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"

workbox-background-sync@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-3.2.0.tgz#08d4f79fb82fb61f72fbd0359c4b616cc75612d4"
dependencies:
workbox-core "^3.2.0"

workbox-broadcast-cache-update@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-broadcast-cache-update/-/workbox-broadcast-cache-update-3.2.0.tgz#65b4d9b3d4594751ab7ce1fee905c08214118fdc"
dependencies:
workbox-core "^3.2.0"

workbox-build@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-3.2.0.tgz#01f4a4f6fb5a94dadd3f86d04480c84578fa1125"
dependencies:
babel-runtime "^6.26.0"
common-tags "^1.4.0"
fs-extra "^4.0.2"
glob "^7.1.2"
joi "^11.1.1"
lodash.template "^4.4.0"
pretty-bytes "^4.0.2"
workbox-background-sync "^3.2.0"
workbox-broadcast-cache-update "^3.2.0"
workbox-cache-expiration "^3.2.0"
workbox-cacheable-response "^3.2.0"
workbox-core "^3.2.0"
workbox-google-analytics "^3.2.0"
workbox-precaching "^3.2.0"
workbox-range-requests "^3.2.0"
workbox-routing "^3.2.0"
workbox-strategies "^3.2.0"
workbox-streams "^3.2.0"
workbox-sw "^3.2.0"

workbox-cache-expiration@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-cache-expiration/-/workbox-cache-expiration-3.2.0.tgz#a585761fd5438e439668afc6f862ac5a0ebca1a8"
dependencies:
workbox-core "^3.2.0"

workbox-cacheable-response@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-3.2.0.tgz#1d8e3d437d60fb80d971d79545bb27acf1fe7653"
dependencies:
workbox-core "^3.2.0"

workbox-core@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-3.2.0.tgz#d1bd4209447f5350d8dd6b964c86f054c96ffa0a"

workbox-google-analytics@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-3.2.0.tgz#1005bc71ae03a8948b687896235dafecb1696c46"
dependencies:
workbox-background-sync "^3.2.0"
workbox-core "^3.2.0"
workbox-routing "^3.2.0"
workbox-strategies "^3.2.0"

workbox-precaching@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-3.2.0.tgz#36568687a5615d8bd4191b38cf0f489a992d7bbc"
dependencies:
workbox-core "^3.2.0"

workbox-range-requests@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-3.2.0.tgz#5d6cc3621cef0951fc9c0549053f8e117736d321"
dependencies:
workbox-core "^3.2.0"

workbox-routing@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-3.2.0.tgz#6aef7622ede2412dd116231f4f9408a6485a4832"
dependencies:
workbox-core "^3.2.0"

workbox-strategies@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-3.2.0.tgz#6cd5f00739764872b77b4c3766a606e43eb7d246"
dependencies:
workbox-core "^3.2.0"

workbox-streams@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-3.2.0.tgz#cac0e4f5693b5e13029cbd7e5fec4eb7fcb30d97"
dependencies:
workbox-core "^3.2.0"

workbox-sw@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-3.2.0.tgz#ccda9adff557ba2233bf1837229144b4a86276cb"

workbox-webpack-plugin@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-3.2.0.tgz#eab74294e88d86f4356a5dbac98cd803b22142b3"
dependencies:
json-stable-stringify "^1.0.1"
workbox-build "^3.2.0"

worker-farm@^1.5.2:
version "1.6.0"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0"
Expand Down

0 comments on commit 9602f76

Please sign in to comment.