Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2): Plugin for Offline/PWA support #2205

Merged
merged 52 commits into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
2d8d8fd
implement PWA plugin
codemonkey800 Feb 5, 2020
e8c9b03
added pwa support for docusaurus website
codemonkey800 Feb 5, 2020
3132752
moved sw registration to client module
codemonkey800 Feb 19, 2020
082fdb5
moved compile function to webpack util
codemonkey800 Feb 26, 2020
27e9d38
build sw using webpack and render pwa popup
codemonkey800 Feb 26, 2020
32346c0
implement @theme/PwaReloadPopup
codemonkey800 Feb 26, 2020
bc2d1d5
update website sw to use modules
codemonkey800 Feb 26, 2020
55bf04d
updated pwa readme
codemonkey800 Feb 26, 2020
2cbc441
fix header lint errors
codemonkey800 Feb 26, 2020
a6c435f
Merge remote-tracking branch 'upstream/master'
codemonkey800 Apr 6, 2020
c45a768
apply code formatting
codemonkey800 Apr 6, 2020
2559f16
cache files only for mobile, saveData, or installed pwa
codemonkey800 Apr 8, 2020
584cc58
Merge remote-tracking branch 'upstream/master'
codemonkey800 Apr 8, 2020
22a76e8
added comments about clearing registrations
codemonkey800 Apr 8, 2020
fbf7789
fixed prettier error
codemonkey800 Apr 8, 2020
e9b7696
updated pwa README
codemonkey800 Apr 8, 2020
3f09483
fix README JS
codemonkey800 Apr 8, 2020
e1a4b01
Merge remote-tracking branch 'upstream/master'
codemonkey800 Apr 8, 2020
bebc51a
move /blog => /blog/index.html logic to else branch
codemonkey800 Apr 8, 2020
5eddf21
add `alwaysPrecache` option
codemonkey800 Apr 8, 2020
d3661a5
Merge remote-tracking branch 'upstream/master'
codemonkey800 Jun 10, 2020
7d0a915
updated docusaurus-plugin-pwa version
codemonkey800 Jun 10, 2020
be6dc4a
added pwa to using-plugins.md
codemonkey800 Jun 10, 2020
34e3434
review fixes
codemonkey800 Jun 10, 2020
03d0d10
Merge remote-tracking branch 'upstream/master'
codemonkey800 Jun 11, 2020
b27c64d
Merge remote-tracking branch 'upstream/master'
codemonkey800 Jun 28, 2020
c1d79ee
re-disable restricted-globals to use self in service worker
codemonkey800 Jun 29, 2020
283f64f
useless doc
slorber Jul 6, 2020
b5f213e
Merge remote-tracking branch 'upstream/master'
slorber Jul 6, 2020
ca5ed14
Update packages/docusaurus-plugin-pwa/README.md
slorber Jul 6, 2020
0cbad2a
Update packages/docusaurus-plugin-pwa/README.md
slorber Jul 6, 2020
37f6cde
update a bit pwa doc + minor refactors
slorber Jul 6, 2020
28ade9a
minor refactors + add workbox debug mode
slorber Jul 6, 2020
cf0dd42
env PWA_ prefix
slorber Jul 6, 2020
1b13340
typo
slorber Jul 6, 2020
5a7ed5a
minor refactor
slorber Jul 6, 2020
da67c42
fix file output
slorber Jul 6, 2020
e71280a
add serve:v2:ssl yarn command
slorber Jul 6, 2020
9bc28c5
minor pwa fixes
slorber Jul 6, 2020
f8b71ec
typo
slorber Jul 6, 2020
c71373f
add dynamic import comment in SW
slorber Jul 6, 2020
bad56ac
comment
slorber Jul 6, 2020
4e49004
let the PWA plugin implement its reload popup on his own
slorber Jul 6, 2020
fedc331
pwa: add Joi options validation
slorber Jul 6, 2020
313e8c5
pwa plugin should have its own webpack/babel custom setup
slorber Jul 7, 2020
dc063de
PWA:
slorber Jul 7, 2020
3becaa7
add pwa install gif
slorber Jul 7, 2020
dfbc75b
pwa: popup -> reloadPopup + minor refactors
slorber Jul 7, 2020
820128a
fix process.env reading + better debug log
slorber Jul 7, 2020
8112260
minor fixes
slorber Jul 7, 2020
788f831
minor changes
slorber Jul 8, 2020
0e0b219
minor changes
slorber Jul 8, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"build:v2": "yarn workspace docusaurus-2-website build",
"serve:v1": "serve website-1.x/build/docusaurus",
"serve:v2": "serve website/build",
"serve:v2:ssl": "yarn serve:v2:ssl:gencert && yarn serve:v2:ssl:message && yarn serve:v2:ssl:serve",
"serve:v2:ssl:gencert": "openssl req -x509 -nodes -days 365 -newkey rsa:4096 -subj \"/C=US/ST=Docusaurus/L=Anywhere/O=Dis/CN=localhost\" -keyout ./website/.docusaurus/selfsigned.key -out ./website/.docusaurus/selfsigned.crt",
"serve:v2:ssl:message": "echo '\n\n\nServing Docusaurus with HTTPS on localhost requires to disable the Chrome security: chrome://flags/#allow-insecure-localhost\n\n\n'",
"serve:v2:ssl:serve": "serve website/build --ssl-cert ./website/.docusaurus/selfsigned.crt --ssl-key ./website/.docusaurus/selfsigned.key",
"changelog": "lerna-changelog",
"postinstall": "yarn build:packages",
"prettier": "prettier --config .prettierrc --write \"**/*.{js,ts}\"",
Expand Down
29 changes: 29 additions & 0 deletions packages/docusaurus-plugin-pwa/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "@docusaurus/plugin-pwa",
"version": "2.0.0-alpha.58",
"description": "Docusaurus Plugin to add PWA support",
"main": "src/index.js",
"publishConfig": {
"access": "public"
},
"license": "MIT",
"dependencies": {
"@babel/preset-env": "^7.9.0",
"@babel/plugin-proposal-optional-chaining": "^7.10.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
"@hapi/joi": "^17.1.1",
"babel-loader": "^8.1.0",
"core-js": "^2.6.5",
"terser-webpack-plugin": "^2.3.5",
"webpack-merge": "^4.2.2",
"webpack": "^4.41.2",
"workbox-build": "^5.1.2",
slorber marked this conversation as resolved.
Show resolved Hide resolved
"workbox-precaching": "^5.1.2",
"workbox-window": "^5.1.2"
},
"peerDependencies": {
"@docusaurus/core": "^2.0.0",
"react": "^16.8.4",
"react-dom": "^16.8.4"
}
}
173 changes: 173 additions & 0 deletions packages/docusaurus-plugin-pwa/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

const LogPlugin = require('@docusaurus/core/lib/webpack/plugins/LogPlugin');
const {compile} = require('@docusaurus/core/lib/webpack/utils');
const path = require('path');
const webpack = require('webpack');
const {injectManifest} = require('workbox-build');
const {PluginOptionSchema} = require('./pluginOptionSchema');
const Terser = require('terser-webpack-plugin');

const isProd = process.env.NODE_ENV === 'production';

function getSWBabelLoader() {
return {
loader: 'babel-loader',
options: {
babelrc: false,
configFile: false,
presets: [
[
require.resolve('@babel/preset-env'),
{
useBuiltIns: 'usage',
corejs: '2',
// See https://twitter.com/jeffposnick/status/1280223070876315649
targets: 'chrome >= 56',
},
],
],
plugins: [
require.resolve('@babel/plugin-proposal-object-rest-spread'),
require.resolve('@babel/plugin-proposal-optional-chaining'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
],
},
};
}

function plugin(context, options) {
const {outDir, baseUrl} = context;
const {
debug,
offlineModeActivationStrategies,
injectManifestConfig,
reloadPopup,
pwaHead,
swCustom,
swRegister,
} = options;

return {
name: 'docusaurus-plugin-pwa',

getThemePath() {
return path.resolve(__dirname, './theme');
},

getClientModules() {
return isProd ? [swRegister] : [];
slorber marked this conversation as resolved.
Show resolved Hide resolved
},

configureWebpack(config) {
if (!isProd) {
return {};
}

return {
plugins: [
new webpack.EnvironmentPlugin({
PWA_DEBUG: debug,
PWA_SERVICE_WORKER_URL: path.resolve(
`${config.output.publicPath || '/'}`,
'sw.js',
),
PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES: offlineModeActivationStrategies,
PWA_RELOAD_POPUP: reloadPopup,
}),
],
};
},

injectHtmlTags() {
const headTags = [];
if (isProd && pwaHead) {
pwaHead.forEach(({tagName, ...attributes}) =>
headTags.push({
slorber marked this conversation as resolved.
Show resolved Hide resolved
tagName,
attributes,
}),
);
}
return {headTags};
},

async postBuild(props) {
if (!isProd) {
return;
}

slorber marked this conversation as resolved.
Show resolved Hide resolved
const swSourceFileTest = /\.m?js$/;

const swWebpackConfig = {
entry: path.resolve(__dirname, 'sw.js'),
output: {
path: outDir,
filename: 'sw.js',
publicPath: baseUrl,
},
target: 'webworker',
mode: debug ? 'development' : 'production',
devtool: debug ? 'source-map' : false,
optimization: {
splitChunks: false,
minimize: !debug,
// see https://developers.google.com/web/tools/workbox/guides/using-bundlers#webpack
minimizer: [
!debug &&
new Terser({
test: swSourceFileTest,
}),
].filter(Boolean),
},
plugins: [
new webpack.EnvironmentPlugin({
PWA_SW_CUSTOM: swCustom,
}),
new LogPlugin({
name: 'Service Worker',
color: 'red',
}),
],
module: {
rules: [
{
test: swSourceFileTest,
exclude: /(node_modules)/,
use: getSWBabelLoader(),
},
],
},
};

await compile([swWebpackConfig]);

const swDest = path.resolve(props.outDir, 'sw.js');

await injectManifest({
...injectManifestConfig,
globPatterns: [
'**/*.{js,json,css,html}',
'**/*.{png,jpg,jpeg,gif,svg,ico}',
'**/*.{woff,woff2,eot,ttf,otf}',
...(injectManifest.globPatterns || []),
],
// those attributes are not overrideable
swDest,
swSrc: swDest,
globDirectory: props.outDir,
});
},
};
}

module.exports = plugin;

plugin.validateOptions = function validateOptions({validate, options}) {
return validate(PluginOptionSchema, options);
};
43 changes: 43 additions & 0 deletions packages/docusaurus-plugin-pwa/src/pluginOptionSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

const Joi = require('@hapi/joi');
const path = require('path');

const DEFAULT_OPTIONS = {
debug: false,
offlineModeActivationStrategies: ['appInstalled', 'queryString'],
injectManifestConfig: {},
pwaHead: [],
swCustom: undefined,
swRegister: path.join(__dirname, 'registerSw.js'),
reloadPopup: '@theme/PwaReloadPopup',
};

exports.PluginOptionSchema = Joi.object({
debug: Joi.bool().default(DEFAULT_OPTIONS.debug),
offlineModeActivationStrategies: Joi.array()
.items(
Joi.string()
.valid('appInstalled', 'queryString', 'mobile', 'saveData', 'always')
.required(),
)
.default(DEFAULT_OPTIONS.offlineModeActivationStrategies),
injectManifestConfig: Joi.object().default(
DEFAULT_OPTIONS.injectManifestConfig,
),
pwaHead: Joi.array()
.items(Joi.object({tagName: Joi.string().required()}).unknown().required())
.default(DEFAULT_OPTIONS.pwaHead),
swCustom: Joi.string(),
swRegister: Joi.alternatives()
.try(Joi.string(), Joi.bool().valid(false))
.default(DEFAULT_OPTIONS.swRegister),
reloadPopup: Joi.alternatives()
.try(Joi.string(), Joi.bool().valid(false))
.default(DEFAULT_OPTIONS.reloadPopup),
});
Loading