forked from excalidraw/excalidraw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathservice-worker.ts
147 lines (130 loc) · 4.66 KB
/
service-worker.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/// <reference lib="webworker" />
/* eslint-disable no-restricted-globals */
// This service worker can be customized!
// See https://developers.google.com/web/tools/workbox/modules
// for the list of available Workbox modules, or add any other
// code you'd like.
// You can also remove this file if you'd prefer not to use a
// service worker, and the Workbox build step will be skipped.
import { clientsClaim } from "workbox-core";
import { ExpirationPlugin } from "workbox-expiration";
import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
import { CacheFirst, StaleWhileRevalidate } from "workbox-strategies";
declare const self: ServiceWorkerGlobalScope;
clientsClaim();
// Precache assets generated by your build process.
//
// Their URLs are injected into the __WB_MANIFEST during build (by workbox).
//
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA.
//
// We don't want to precache i18n files so we filter them out
// (normally this should be configured in a webpack workbox plugin, but we don't
// have access to it in CRA) — this is because all users will use at most
// one or two languages, so there's no point fetching all of them. (They'll
// be cached as you load them.)
const manifest = self.__WB_MANIFEST.filter((entry) => {
return !/locales\/[\w-]+json/.test(
typeof entry === "string" ? entry : entry.url,
);
});
precacheAndRoute(manifest);
// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developer.chrome.com/docs/workbox/app-shell-model/
//
// below is copied verbatim from CRA@5
const fileExtensionRegexp = new RegExp("/[^/?]+\\.[^/]+$");
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({ request, url }: { request: Request; url: URL }) => {
// If this isn't a navigation, skip.
if (request.mode !== "navigate") {
return false;
}
// If this is a URL that starts with /_, skip.
if (url.pathname.startsWith("/_")) {
return false;
}
// If this looks like a URL for a resource, because it contains
// a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
return false;
}
// Return true to signal that we want to use the handler.
return true;
},
createHandlerBoundToURL(`${process.env.PUBLIC_URL}/index.html`),
);
// Cache resources that aren't being precached
// -----------------------------------------------------------------------------
registerRoute(
new RegExp("/fonts.css"),
new StaleWhileRevalidate({
cacheName: "fonts",
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({ maxEntries: 50 }),
],
}),
);
// since we serve fonts from, don't forget to append new ?v= param when
// updating fonts (glyphs) without changing the filename
registerRoute(
new RegExp("/.+.(ttf|woff2|otf)"),
new CacheFirst({
cacheName: "fonts",
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({
maxEntries: 50,
// 90 days
maxAgeSeconds: 7776000000,
}),
],
}),
);
registerRoute(
new RegExp("/locales\\/[\\w-]+json"),
// Customize this strategy as needed, e.g., by changing to CacheFirst.
new CacheFirst({
cacheName: "locales",
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({
maxEntries: 50,
// 30 days
maxAgeSeconds: 2592000000,
}),
],
}),
);
// -----------------------------------------------------------------------------
self.addEventListener("fetch", (event) => {
if (
event.request.method === "POST" &&
event.request.url.endsWith("/web-share-target")
) {
return event.respondWith(
(async () => {
const formData = await event.request.formData();
const file = formData.get("file");
const webShareTargetCache = await caches.open("web-share-target");
await webShareTargetCache.put("shared-file", new Response(file));
return Response.redirect("/?web-share-target", 303);
})(),
);
}
});
// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") {
self.skipWaiting();
}
});