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

Move serviceworker to workbox and fix SSE interference #11538

Merged
merged 13 commits into from
May 22, 2020
Next Next commit
Move serviceworker to workbox and fix SSE interference
Instead of statically hardcoding every frontend asset, this uses a
type-based approach to cache all js,css and manifest.json requests.

This also fixes the issue that the service worker was interfering with
EventSource because it was unconditionally handling all requests which
this new implementation doesn't.

Fixes: #11092
Fixes: #7372
  • Loading branch information
silverwind committed May 21, 2020
commit 99d9b0f728536f682b458824371c60b9af1a4edd
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"webpack": "4.43.0",
"webpack-cli": "3.3.11",
"webpack-fix-style-only-entries": "0.4.0",
"workbox-routing": "5.1.3",
"workbox-strategies": "5.1.3",
"worker-loader": "2.0.0"
},
"devDependencies": {
Expand Down
4 changes: 0 additions & 4 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -1048,10 +1048,6 @@ func RegisterRoutes(m *macaron.Macaron) {
ctx.HTML(200, "pwa/manifest_json")
})

m.Get("/serviceworker.js", templates.JSRenderer(), func(ctx *context.Context) {
ctx.HTML(200, "pwa/serviceworker_js")
})

// prometheus metrics endpoint
if setting.Metrics.Enabled {
c := metrics.NewCollector()
Expand Down
25 changes: 1 addition & 24 deletions templates/base/head.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,6 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}} </title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) {
// Registration was successful
console.info('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.info('ServiceWorker registration failed: ', err);
});
}
</script>
{{else}}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(function(registrations) {
registrations.forEach(function(registration) {
registration.unregister();
console.info('ServiceWorker unregistered');
});
});
}
</script>
{{end}}
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" />
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" />
Expand Down Expand Up @@ -86,6 +62,7 @@
window.config = {
AppSubUrl: '{{AppSubUrl}}',
StaticUrlPrefix: '{{StaticUrlPrefix}}',
UseServiceWorker: {{UseServiceWorker}},
csrf: '{{.CsrfToken}}',
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}},
Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}},
Expand Down
83 changes: 0 additions & 83 deletions templates/pwa/serviceworker_js.tmpl

This file was deleted.

24 changes: 24 additions & 0 deletions web_src/js/features/serviceworker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const {UseServiceWorker, AppSubUrl} = window.config;

async function unregister() {
for (const registration of await navigator.serviceWorker.getRegistrations()) {
const serviceWorker = registration.active;
if (!serviceWorker) continue;
registration.unregister();
}
}

export default async function initServiceWorker() {
if (!('serviceWorker' in navigator)) return;

if (UseServiceWorker) {
try {
navigator.serviceWorker.register(`${AppSubUrl}/serviceworker.js`);
} catch (err) {
console.error(err);
await unregister();
}
} else {
await unregister();
}
}
2 changes: 2 additions & 0 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import initGitGraph from './features/gitgraph.js';
import initClipboard from './features/clipboard.js';
import initUserHeatmap from './features/userheatmap.js';
import initDateTimePicker from './features/datetimepicker.js';
import initServiceWorker from './features/serviceworker.js';
import attachTribute from './features/tribute.js';
import createDropzone from './features/dropzone.js';
import highlight from './features/highlight.js';
Expand Down Expand Up @@ -2475,6 +2476,7 @@ $(document).ready(async () => {
initGitGraph(),
initClipboard(),
initUserHeatmap(),
initServiceWorker(),
]);
});

Expand Down
14 changes: 14 additions & 0 deletions web_src/js/serviceworker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

const cachedDestinations = new Set([
'manifest',
'script',
'style',
'worker',
]);

registerRoute(
({request}) => cachedDestinations.has(request.destination),
new StaleWhileRevalidate({cacheName: 'static-cache-v2'}),
);
9 changes: 8 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,20 @@ module.exports = {
jquery: [
resolve(__dirname, 'web_src/js/jquery.js'),
],
serviceworker: [
resolve(__dirname, 'web_src/js/serviceworker.js'),
],
icons: glob('node_modules/@primer/octicons/build/svg/**/*.svg'),
...themes,
},
devtool: false,
output: {
path: resolve(__dirname, 'public'),
filename: 'js/[name].js',
filename: ({chunk}) => {
// serviceworker can only manage assets below it's script path so we
// have to put it in / instead of /js/
return chunk.id === 'serviceworker' ? '[name].js' : 'js/[name].js';
},
chunkFilename: 'js/[name].js',
},
optimization: {
Expand Down