Skip to content

Commit 99d9b0f

Browse files
committed
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
1 parent 460bc32 commit 99d9b0f

File tree

9 files changed

+73
-112
lines changed

9 files changed

+73
-112
lines changed

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
"webpack": "4.43.0",
4949
"webpack-cli": "3.3.11",
5050
"webpack-fix-style-only-entries": "0.4.0",
51+
"workbox-routing": "5.1.3",
52+
"workbox-strategies": "5.1.3",
5153
"worker-loader": "2.0.0"
5254
},
5355
"devDependencies": {

routers/routes/routes.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,10 +1048,6 @@ func RegisterRoutes(m *macaron.Macaron) {
10481048
ctx.HTML(200, "pwa/manifest_json")
10491049
})
10501050

1051-
m.Get("/serviceworker.js", templates.JSRenderer(), func(ctx *context.Context) {
1052-
ctx.HTML(200, "pwa/serviceworker_js")
1053-
})
1054-
10551051
// prometheus metrics endpoint
10561052
if setting.Metrics.Enabled {
10571053
c := metrics.NewCollector()

templates/base/head.tmpl

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,6 @@
66
<meta http-equiv="x-ua-compatible" content="ie=edge">
77
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}} </title>
88
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
9-
{{if UseServiceWorker}}
10-
<script>
11-
if ('serviceWorker' in navigator) {
12-
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) {
13-
// Registration was successful
14-
console.info('ServiceWorker registration successful with scope: ', registration.scope);
15-
}, function(err) {
16-
// registration failed :(
17-
console.info('ServiceWorker registration failed: ', err);
18-
});
19-
}
20-
</script>
21-
{{else}}
22-
<script>
23-
if ('serviceWorker' in navigator) {
24-
navigator.serviceWorker.getRegistrations().then(function(registrations) {
25-
registrations.forEach(function(registration) {
26-
registration.unregister();
27-
console.info('ServiceWorker unregistered');
28-
});
29-
});
30-
}
31-
</script>
32-
{{end}}
339
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
3410
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" />
3511
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" />
@@ -86,6 +62,7 @@
8662
window.config = {
8763
AppSubUrl: '{{AppSubUrl}}',
8864
StaticUrlPrefix: '{{StaticUrlPrefix}}',
65+
UseServiceWorker: {{UseServiceWorker}},
8966
csrf: '{{.CsrfToken}}',
9067
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}},
9168
Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}},

templates/pwa/serviceworker_js.tmpl

Lines changed: 0 additions & 83 deletions
This file was deleted.

web_src/js/features/serviceworker.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const {UseServiceWorker, AppSubUrl} = window.config;
2+
3+
async function unregister() {
4+
for (const registration of await navigator.serviceWorker.getRegistrations()) {
5+
const serviceWorker = registration.active;
6+
if (!serviceWorker) continue;
7+
registration.unregister();
8+
}
9+
}
10+
11+
export default async function initServiceWorker() {
12+
if (!('serviceWorker' in navigator)) return;
13+
14+
if (UseServiceWorker) {
15+
try {
16+
navigator.serviceWorker.register(`${AppSubUrl}/serviceworker.js`);
17+
} catch (err) {
18+
console.error(err);
19+
await unregister();
20+
}
21+
} else {
22+
await unregister();
23+
}
24+
}

web_src/js/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import initGitGraph from './features/gitgraph.js';
1414
import initClipboard from './features/clipboard.js';
1515
import initUserHeatmap from './features/userheatmap.js';
1616
import initDateTimePicker from './features/datetimepicker.js';
17+
import initServiceWorker from './features/serviceworker.js';
1718
import attachTribute from './features/tribute.js';
1819
import createDropzone from './features/dropzone.js';
1920
import highlight from './features/highlight.js';
@@ -2475,6 +2476,7 @@ $(document).ready(async () => {
24752476
initGitGraph(),
24762477
initClipboard(),
24772478
initUserHeatmap(),
2479+
initServiceWorker(),
24782480
]);
24792481
});
24802482

web_src/js/serviceworker.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {registerRoute} from 'workbox-routing';
2+
import {StaleWhileRevalidate} from 'workbox-strategies';
3+
4+
const cachedDestinations = new Set([
5+
'manifest',
6+
'script',
7+
'style',
8+
'worker',
9+
]);
10+
11+
registerRoute(
12+
({request}) => cachedDestinations.has(request.destination),
13+
new StaleWhileRevalidate({cacheName: 'static-cache-v2'}),
14+
);

webpack.config.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,20 @@ module.exports = {
3535
jquery: [
3636
resolve(__dirname, 'web_src/js/jquery.js'),
3737
],
38+
serviceworker: [
39+
resolve(__dirname, 'web_src/js/serviceworker.js'),
40+
],
3841
icons: glob('node_modules/@primer/octicons/build/svg/**/*.svg'),
3942
...themes,
4043
},
4144
devtool: false,
4245
output: {
4346
path: resolve(__dirname, 'public'),
44-
filename: 'js/[name].js',
47+
filename: ({chunk}) => {
48+
// serviceworker can only manage assets below it's script path so we
49+
// have to put it in / instead of /js/
50+
return chunk.id === 'serviceworker' ? '[name].js' : 'js/[name].js';
51+
},
4552
chunkFilename: 'js/[name].js',
4653
},
4754
optimization: {

0 commit comments

Comments
 (0)