mirror of
https://github.com/jcreek/SelectionWheel.git
synced 2026-07-12 18:53:45 +00:00
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:
Generated
+4700
-718
File diff suppressed because it is too large
Load Diff
+15
-7
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "SelectionWheel",
|
"name": "SelectionWheel",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"description": "A fun and simple selection wheel.",
|
"description": "A fun and simple selection wheel.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack --config webpack.prod.js",
|
||||||
"dev": "webpack serve",
|
"dev": "webpack serve --hot --config webpack.dev.js",
|
||||||
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts ."
|
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts ."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -27,8 +27,6 @@
|
|||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
|
||||||
"react-dev-utils": "^12.0.1",
|
|
||||||
"sass": "^1.52.3",
|
"sass": "^1.52.3",
|
||||||
"sass-loader": "^13.0.0",
|
"sass-loader": "^13.0.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
@@ -36,10 +34,20 @@
|
|||||||
"webpack": "^5.73.0",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-dev-server": "^4.9.2",
|
"webpack-dev-server": "^4.9.2",
|
||||||
"webpack-webmanifest-loader": "^2.0.2"
|
"webpack-webmanifest-loader": "^2.0.2",
|
||||||
|
"workbox-cli": "^6.5.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/d3": "^7.4.0",
|
"@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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
"description": "A fun and simple selection wheel.",
|
"description": "A fun and simple selection wheel.",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "./android-chrome-192x192.png",
|
"src": "android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "./android-chrome-512x512.png",
|
"src": "android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
import loadServiceWorker from './loadServiceWorker';
|
||||||
|
|
||||||
require('./assets/favicon.ico');
|
require('./assets/favicon.ico');
|
||||||
require('./assets/android-chrome-192x192.png');
|
require('./assets/android-chrome-192x192.png');
|
||||||
@@ -208,3 +209,7 @@ function startSpinning() {
|
|||||||
|
|
||||||
const button = document.getElementById('startSpinning');
|
const button = document.getElementById('startSpinning');
|
||||||
button.onclick = startSpinning;
|
button.onclick = startSpinning;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
loadServiceWorker();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
@@ -26,5 +26,11 @@
|
|||||||
<textarea id="input-lines" rows="15" cols="60" name="text"
|
<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>
|
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>
|
<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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||||
|
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
|
||||||
|
|
||||||
|
const options = {};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'development',
|
target: 'web',
|
||||||
entry: {
|
entry: {
|
||||||
bundle: path.resolve(__dirname, 'src/index.ts'),
|
bundle: path.resolve(__dirname, 'src/index.ts'),
|
||||||
},
|
},
|
||||||
@@ -12,23 +15,7 @@ module.exports = {
|
|||||||
filename: '[name].[contenthash].js',
|
filename: '[name].[contenthash].js',
|
||||||
clean: true,
|
clean: true,
|
||||||
assetModuleFilename: '[name].[contenthash][ext]',
|
assetModuleFilename: '[name].[contenthash][ext]',
|
||||||
publicPath: './',
|
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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
watchOptions: { poll: true },
|
watchOptions: { poll: true },
|
||||||
module: {
|
module: {
|
||||||
@@ -100,5 +87,6 @@ module.exports = {
|
|||||||
template: 'src/template.html',
|
template: 'src/template.html',
|
||||||
}),
|
}),
|
||||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/.*/]),
|
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/.*/]),
|
||||||
|
new WebpackManifestPlugin(options),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -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,
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user