Skip to content

Commit 3854b23

Browse files
EugeneHlushkomontogeek
authored andcommitted
feat(pwa) use offline-plugin for service worker setup and offline sup… (#3000)
* feat(pwa) use offline-plugin for service worker setup and offline support * feat(pwa) the whole website works offline * feat(pwa) make sure prod build runs after ssg. Provide css from ssg run to prod SW * feat(pwa) remove appShell option from offline-plugin * feat(pwa) make site work offline and respect SSG css * feat(pwa) offline works for home and for other pages * feat(pwa) use proper app shell for all pages cept home * feat(pwa) make real app shell for doc pages, only pre cache hp and app shell, now everything offline
1 parent cac1fe1 commit 3854b23

File tree

7 files changed

+158
-102
lines changed

7 files changed

+158
-102
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"fetch:supporters": "node src/utilities/fetch-supporters.js",
3636
"fetch:starter-kits": "node src/utilities/fetch-starter-kits.js",
3737
"prebuild": "npm run clean",
38-
"build": "run-s fetch content && cross-env NODE_ENV=production webpack --config webpack.prod.js",
38+
"build": "run-s fetch content && cross-env NODE_ENV=production webpack --config webpack.ssg.js && cross-env NODE_ENV=production webpack --config webpack.prod.js",
3939
"postbuild": "npm run sitemap",
4040
"test": "npm run lint",
4141
"lint": "run-s lint:*",
@@ -109,6 +109,7 @@
109109
"modularscale-sass": "^3.0.3",
110110
"node-sass": "^4.5.3",
111111
"npm-run-all": "^4.1.1",
112+
"offline-plugin": "^5.0.7",
112113
"optimize-css-assets-webpack-plugin": "^5.0.1",
113114
"postcss-loader": "^2.1.3",
114115
"redirect-webpack-plugin": "^0.1.1",

src/components/Site/Site.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ import './Site.scss';
3131
// Load Content Tree
3232
import Content from '../../_content.json';
3333

34+
// call offline plugin so it can build
35+
if (isClient) {
36+
require('offline-plugin/runtime').install();
37+
}
38+
3439
class Site extends React.Component {
3540
state = {
3641
mobileSidebarOpen: false
@@ -77,6 +82,7 @@ class Site extends React.Component {
7782
<Route path="/vote" component={Vote} />
7883
<Route path="/organization" component={Organization} />
7984
<Route path="/starter-kits" component={StarterKits} />
85+
<Route path="/app-shell" component={() => <React.Fragment />} />
8086
{pages.map(page => (
8187
<Route
8288
key={page.url}

src/utilities/find-files-in-dist.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// grab .css files from ssg run
2+
const fs = require('fs');
3+
4+
module.exports = function (endsWith = false) {
5+
const filesInDist = fs.readdirSync('./dist');
6+
return endsWith
7+
? filesInDist.filter((item) => item.endsWith(endsWith))
8+
: filesInDist;
9+
};

webpack.common.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ module.exports = (env = {}) => ({
148148
output: {
149149
path: path.resolve(__dirname, './dist'),
150150
publicPath: '/',
151-
filename: '[name].bundle.js'
151+
filename: '[name].bundle.js',
152+
chunkFilename: '[name].[chunkhash].chunk.js'
152153
}
153154
});

webpack.prod.js

Lines changed: 21 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,39 @@
11
// Import External Dependencies
22
const merge = require('webpack-merge');
3-
const SSGPlugin = require('static-site-generator-webpack-plugin');
4-
const RedirectWebpackPlugin = require('redirect-webpack-plugin');
5-
const CopyWebpackPlugin = require('copy-webpack-plugin');
6-
const flattenContentTree = require('./src/utilities/flatten-content-tree');
7-
const contentTree = require('./src/_content.json');
83
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
94
const TerserJSPlugin = require('terser-webpack-plugin');
5+
const OfflinePlugin = require('offline-plugin');
106

117
// Load Common Configuration
128
const common = require('./webpack.common.js');
139

14-
// content tree to path array
15-
const paths = [
16-
...flattenContentTree(contentTree),
17-
'/vote',
18-
'/organization',
19-
'/starter-kits'
20-
];
10+
// find css files for sw
11+
const cssFiles = require('./src/utilities/find-files-in-dist')('.css');
12+
// find favicons
13+
const favicons = require('./src/utilities/find-files-in-dist')('.ico');
2114

22-
// Prod only config
23-
const prod = {
15+
// fall back all urls to app shell
16+
17+
module.exports = env => merge(common(env), {
2418
mode: 'production',
19+
target: 'web',
2520
optimization: {
2621
minimizer: [
2722
new TerserJSPlugin({}),
2823
new OptimizeCSSAssetsPlugin({})
2924
]
3025
},
3126
plugins: [
32-
new CopyWebpackPlugin([
33-
{
34-
from: './assets/PWA',
35-
to: './'
36-
},
37-
{
38-
from: './assets/icon-square-small-slack.png',
39-
to: './assets/'
40-
},
41-
{
42-
from: './assets/icon-square-big.svg',
43-
to: './assets/'
44-
},
45-
'CNAME'
46-
])
27+
new OfflinePlugin({
28+
autoUpdate: true,
29+
publicPath: '/',
30+
appShell: '/app-shell/',
31+
// make sure to cache homepage and app shell as app shell for the rest of the pages.
32+
externals: ['/app-shell/', '/', '/manifest.json', ...cssFiles, ...favicons],
33+
excludes: [],
34+
AppCache: {
35+
publicPath: '/'
36+
}
37+
})
4738
]
48-
};
49-
50-
// Export both SSG and SPA configurations
51-
module.exports = env => [
52-
merge(common(env), prod, {
53-
target: 'node',
54-
entry: {
55-
index: './server.jsx'
56-
},
57-
plugins: [
58-
new SSGPlugin({
59-
globals: {
60-
window: {}
61-
},
62-
paths,
63-
locals: {
64-
content: contentTree
65-
}
66-
}),
67-
new RedirectWebpackPlugin({
68-
redirects: {
69-
'support': '/contribute/',
70-
'writers-guide': '/contribute/writers-guide/',
71-
'get-started': '/guides/getting-started/',
72-
'get-started/install-webpack': '/guides/installation/',
73-
'get-started/why-webpack': '/guides/why-webpack/',
74-
'pluginsapi': '/api/plugins/',
75-
'pluginsapi/compiler': '/api/compiler-hooks/',
76-
'pluginsapi/template': '/api/template/',
77-
'api/passing-a-config': '/configuration/configuration-types/',
78-
'api/plugins/compiler': '/api/compiler-hooks/',
79-
'api/plugins/compilation': '/api/compilation/',
80-
'api/plugins/module-factories': '/api/module-methods/',
81-
'api/plugins/parser': '/api/parser/',
82-
'api/plugins/tapable': '/api/tapable/',
83-
'api/plugins/template': '/api/template/',
84-
'api/plugins/resolver': '/api/resolver/',
85-
'development': '/contribute/',
86-
'development/plugin-patterns': '/contribute/plugin-patterns/',
87-
'development/release-process': '/contribute/release-process/',
88-
'development/how-to-write-a-loader': '/contribute/writing-a-loader/',
89-
'development/how-to-write-a-plugin': '/contribute/writing-a-plugin/',
90-
'guides/code-splitting-import': '/guides/code-splitting/',
91-
'guides/code-splitting-require': '/guides/code-splitting/',
92-
'guides/code-splitting-async': '/guides/code-splitting/',
93-
'guides/code-splitting-css': '/guides/code-splitting/',
94-
'guides/code-splitting-libraries': '/guides/code-splitting/',
95-
'guides/why-webpack': '/comparison/',
96-
'guides/production-build': '/guides/production/',
97-
'migrating': '/migrate/3/',
98-
'plugins/no-emit-on-errors-plugin': '/configuration/optimization/#optimization-noemitonerrors',
99-
'concepts/mode': '/configuration/mode'
100-
}
101-
})
102-
],
103-
output: {
104-
filename: 'server.[name].js',
105-
libraryTarget: 'umd'
106-
}
107-
}),
108-
merge(common(env), prod, {
109-
target: 'web'
110-
})
111-
];
39+
});

webpack.ssg.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Import External Dependencies
2+
const merge = require('webpack-merge');
3+
const SSGPlugin = require('static-site-generator-webpack-plugin');
4+
const RedirectWebpackPlugin = require('redirect-webpack-plugin');
5+
const CopyWebpackPlugin = require('copy-webpack-plugin');
6+
const flattenContentTree = require('./src/utilities/flatten-content-tree');
7+
const contentTree = require('./src/_content.json');
8+
9+
// Load Common Configuration
10+
const common = require('./webpack.common.js');
11+
12+
// content tree to path array
13+
const paths = [
14+
...flattenContentTree(contentTree),
15+
'/vote',
16+
'/organization',
17+
'/starter-kits',
18+
'/app-shell'
19+
];
20+
21+
module.exports = env => merge(common(env), {
22+
mode: 'production',
23+
target: 'node',
24+
entry: {
25+
index: './server.jsx'
26+
},
27+
output: {
28+
filename: 'server.[name].js',
29+
libraryTarget: 'umd'
30+
},
31+
optimization: {
32+
splitChunks: false
33+
},
34+
plugins: [
35+
new SSGPlugin({
36+
globals: {
37+
window: {}
38+
},
39+
paths,
40+
locals: {
41+
content: contentTree
42+
}
43+
}),
44+
new RedirectWebpackPlugin({
45+
redirects: {
46+
'support': '/contribute/',
47+
'writers-guide': '/contribute/writers-guide/',
48+
'get-started': '/guides/getting-started/',
49+
'get-started/install-webpack': '/guides/installation/',
50+
'get-started/why-webpack': '/guides/why-webpack/',
51+
'pluginsapi': '/api/plugins/',
52+
'pluginsapi/compiler': '/api/compiler-hooks/',
53+
'pluginsapi/template': '/api/template/',
54+
'api/passing-a-config': '/configuration/configuration-types/',
55+
'api/plugins/compiler': '/api/compiler-hooks/',
56+
'api/plugins/compilation': '/api/compilation/',
57+
'api/plugins/module-factories': '/api/module-methods/',
58+
'api/plugins/parser': '/api/parser/',
59+
'api/plugins/tapable': '/api/tapable/',
60+
'api/plugins/template': '/api/template/',
61+
'api/plugins/resolver': '/api/resolver/',
62+
'development': '/contribute/',
63+
'development/plugin-patterns': '/contribute/plugin-patterns/',
64+
'development/release-process': '/contribute/release-process/',
65+
'development/how-to-write-a-loader': '/contribute/writing-a-loader/',
66+
'development/how-to-write-a-plugin': '/contribute/writing-a-plugin/',
67+
'guides/code-splitting-import': '/guides/code-splitting/',
68+
'guides/code-splitting-require': '/guides/code-splitting/',
69+
'guides/code-splitting-async': '/guides/code-splitting/',
70+
'guides/code-splitting-css': '/guides/code-splitting/',
71+
'guides/code-splitting-libraries': '/guides/code-splitting/',
72+
'guides/why-webpack': '/comparison/',
73+
'guides/production-build': '/guides/production/',
74+
'migrating': '/migrate/3/',
75+
'plugins/no-emit-on-errors-plugin': '/configuration/optimization/#optimization-noemitonerrors',
76+
'concepts/mode': '/configuration/mode'
77+
}
78+
}),
79+
new CopyWebpackPlugin([
80+
{
81+
from: './assets/PWA',
82+
to: './'
83+
},
84+
{
85+
from: './assets/icon-square-small-slack.png',
86+
to: './assets/'
87+
},
88+
{
89+
from: './assets/icon-square-big.svg',
90+
to: './assets/'
91+
},
92+
'CNAME'
93+
])
94+
]
95+
});

yarn.lock

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3057,16 +3057,16 @@ deep-equal@^1.0.0, deep-equal@^1.0.1:
30573057
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
30583058
integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
30593059

3060+
deep-extend@^0.5.1, deep-extend@~0.5.1:
3061+
version "0.5.1"
3062+
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
3063+
integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==
3064+
30603065
deep-extend@^0.6.0:
30613066
version "0.6.0"
30623067
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
30633068
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
30643069

3065-
deep-extend@~0.5.1:
3066-
version "0.5.1"
3067-
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
3068-
integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==
3069-
30703070
deep-is@~0.1.3:
30713071
version "0.1.3"
30723072
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@@ -3434,6 +3434,11 @@ [email protected]:
34343434
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
34353435
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
34363436

3437+
ejs@^2.3.4:
3438+
version "2.6.1"
3439+
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
3440+
integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
3441+
34373442
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.124, electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47:
34383443
version "1.3.125"
34393444
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.125.tgz#dbde0e95e64ebe322db0eca764d951f885a5aff2"
@@ -6374,7 +6379,7 @@ loader-runner@^2.3.0:
63746379
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
63756380
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
63766381

6377-
loader-utils@^0.2.10, loader-utils@^0.2.16:
6382+
loader-utils@0.2.x, loader-utils@^0.2.10, loader-utils@^0.2.16:
63786383
version "0.2.17"
63796384
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
63806385
integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=
@@ -7071,7 +7076,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
70717076
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
70727077
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
70737078

7074-
"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2, minimatch@~3.0.4:
7079+
"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2, minimatch@~3.0.4:
70757080
version "3.0.4"
70767081
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
70777082
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -7666,6 +7671,17 @@ obuf@^1.0.0, obuf@^1.1.2:
76667671
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
76677672
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
76687673

7674+
offline-plugin@^5.0.7:
7675+
version "5.0.7"
7676+
resolved "https://registry.yarnpkg.com/offline-plugin/-/offline-plugin-5.0.7.tgz#26936ad1a7699f4d67e0a095a258972a4ccf1788"
7677+
integrity sha512-ArMFt4QFjK0wg8B5+R/6tt65u6Dk+Pkx4PAcW5O7mgIF3ywMepaQqFOQgfZD4ybanuGwuJihxUwMRgkzd+YGYw==
7678+
dependencies:
7679+
deep-extend "^0.5.1"
7680+
ejs "^2.3.4"
7681+
loader-utils "0.2.x"
7682+
minimatch "^3.0.3"
7683+
slash "^1.0.0"
7684+
76697685
on-finished@~2.3.0:
76707686
version "2.3.0"
76717687
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"

0 commit comments

Comments
 (0)