Merge pull request #9 from jcreek/6-add-service-worker-so-it-can-be-used-offline-and-installed-as-a-pwa

6 add service worker so it can be used offline and installed as a pwa
This commit is contained in:
Josh Creek
2022-10-08 00:45:52 +01:00
committed by GitHub
10 changed files with 4826 additions and 745 deletions
+4700 -718
View File
File diff suppressed because it is too large Load Diff
+15 -7
View File
@@ -1,11 +1,11 @@
{
"name": "SelectionWheel",
"version": "1.0.0",
"version": "1.1.0",
"description": "A fun and simple selection wheel.",
"main": "index.js",
"scripts": {
"build": "webpack",
"dev": "webpack serve",
"build": "webpack --config webpack.prod.js",
"dev": "webpack serve --hot --config webpack.dev.js",
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts ."
},
"repository": {
@@ -27,8 +27,6 @@
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"react-dev-utils": "^12.0.1",
"sass": "^1.52.3",
"sass-loader": "^13.0.0",
"style-loader": "^3.3.1",
@@ -36,10 +34,20 @@
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.2",
"webpack-webmanifest-loader": "^2.0.2"
"webpack-webmanifest-loader": "^2.0.2",
"workbox-cli": "^6.5.4"
},
"dependencies": {
"@types/d3": "^7.4.0",
"d3": "^7.6.1"
"d3": "^7.6.1",
"html-webpack-plugin": "^5.5.0",
"react-dev-utils": "^12.0.1",
"webpack-manifest-plugin": "^5.0.0",
"webpack-merge": "^5.8.0",
"workbox-navigation-preload": "^6.5.4",
"workbox-precaching": "^6.5.4",
"workbox-routing": "^6.5.4",
"workbox-strategies": "^6.5.4",
"workbox-webpack-plugin": "^6.5.4"
}
}
+2 -2
View File
@@ -4,12 +4,12 @@
"description": "A fun and simple selection wheel.",
"icons": [
{
"src": "./android-chrome-192x192.png",
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./android-chrome-512x512.png",
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
+5
View File
@@ -1,4 +1,5 @@
import * as d3 from 'd3';
import loadServiceWorker from './loadServiceWorker';
require('./assets/favicon.ico');
require('./assets/android-chrome-192x192.png');
@@ -208,3 +209,7 @@ function startSpinning() {
const button = document.getElementById('startSpinning');
button.onclick = startSpinning;
if (process.env.NODE_ENV === 'production') {
loadServiceWorker();
}
+28
View File
@@ -0,0 +1,28 @@
export default function loadServiceWorker() {
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
const installApp = document.getElementById('install-offline-app');
installApp.addEventListener('click', async () => {
if (deferredPrompt !== null) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
deferredPrompt = null;
}
}
});
document.getElementById('install-app-btn-container').style.display = 'block';
deferredPrompt = e;
});
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
if (window.matchMedia('(display-mode: standalone)').matches) {
document.getElementById('install-app-btn-container').style.display = 'none';
}
}
+22
View File
@@ -0,0 +1,22 @@
import { precacheAndRoute } from 'workbox-precaching';
import * as navigationPreload from 'workbox-navigation-preload';
import { NetworkFirst, CacheFirst } from 'workbox-strategies';
import { registerRoute, NavigationRoute, Route } from 'workbox-routing';
// Precache the manifest
// eslint-disable-next-line no-underscore-dangle, no-restricted-globals
precacheAndRoute(self.__WB_MANIFEST);
// Enable navigation preload - this should reduce navigation latency
navigationPreload.enable();
const navigationRoute = new NavigationRoute(new NetworkFirst({
cacheName: 'navigations',
}));
const imageAssetRoute = new Route(({ request }) => request.destination === 'image', new CacheFirst({
cacheName: 'image-assets',
}));
registerRoute(navigationRoute);
registerRoute(imageAssetRoute);
+6
View File
@@ -26,5 +26,11 @@
<textarea id="input-lines" rows="15" cols="60" name="text"
placeholder="Enter names to be shuffled, one per line. Leave this area empty in order to use a default set of generated names."></textarea>
<button id="startSpinning">Start spinning</button>
<p id="install-app-btn-container">
<button id="install-offline-app" class="btn btn-secondary btn-xs">
<span>Install the app (you can even use it offline!)</span>
</button>
</p>
</body>
</html>
+6 -18
View File
@@ -1,9 +1,12 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const options = {};
module.exports = {
mode: 'development',
target: 'web',
entry: {
bundle: path.resolve(__dirname, 'src/index.ts'),
},
@@ -12,23 +15,7 @@ module.exports = {
filename: '[name].[contenthash].js',
clean: true,
assetModuleFilename: '[name].[contenthash][ext]',
publicPath: './',
},
devtool: 'source-map',
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
port: 3000,
open: true,
hot: true,
compress: true,
historyApiFallback: true,
devMiddleware: {
index: true,
mimeTypes: { phtml: 'text/html' },
writeToDisk: true,
},
publicPath: '',
},
watchOptions: { poll: true },
module: {
@@ -100,5 +87,6 @@ module.exports = {
template: 'src/template.html',
}),
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/.*/]),
new WebpackManifestPlugin(options),
],
};
+23
View File
@@ -0,0 +1,23 @@
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
port: 3000,
open: true,
hot: true,
compress: true,
historyApiFallback: true,
devMiddleware: {
index: true,
mimeTypes: { phtml: 'text/html' },
writeToDisk: true,
},
},
});
+19
View File
@@ -0,0 +1,19 @@
const merge = require('webpack-merge');
const { InjectManifest } = require('workbox-webpack-plugin');
const common = require('./webpack.common');
common.plugins.push(new InjectManifest({
swSrc: './src/serviceWorker.js',
swDest: 'service-worker.js',
maximumFileSizeToCacheInBytes: 50000000,
}));
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
});