Skip to content

Commit b6a66da

Browse files
committed
added lost sw templates
1 parent 2bb73bf commit b6a66da

File tree

5 files changed

+306
-7
lines changed

5 files changed

+306
-7
lines changed

.gitignore

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,10 @@ dist
8080
# IDE / Editor
8181
.idea
8282

83-
# Service worker
84-
sw.*
83+
8584

8685
# macOS
8786
.DS_Store
8887

8988
# Vim swap files
9089
*.swp
91-
92-
# Service Workers
93-
firebase-auth-sw.js
94-
firebase-messaging-sw.js
95-
sw.js

packages/demo/static/sw.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
const options = {"workboxURL":"https://cdn.jsdelivr.net/npm/workbox-cdn@5.1.4/workbox/workbox-sw.js","importScripts":["/firebase-auth-sw.js"],"config":{"debug":true},"cacheOptions":{"cacheId":"nuxt-firebase-demo-dev","directoryIndex":"/","revision":"v5Lq3g0vWFvn"},"clientsClaim":true,"skipWaiting":true,"cleanupOutdatedCaches":true,"offlineAnalytics":false,"preCaching":[{"revision":"v5Lq3g0vWFvn","url":"/?standalone=true"}],"runtimeCaching":[{"urlPattern":"/_nuxt/","handler":"NetworkFirst","method":"GET","strategyPlugins":[]},{"urlPattern":"/","handler":"NetworkFirst","method":"GET","strategyPlugins":[]}],"offlinePage":null,"pagesURLPattern":"/","offlineStrategy":"NetworkFirst"}
2+
3+
importScripts(...[options.workboxURL, ...options.importScripts])
4+
5+
initWorkbox(workbox, options)
6+
workboxExtensions(workbox, options)
7+
precacheAssets(workbox, options)
8+
cachingExtensions(workbox, options)
9+
runtimeCaching(workbox, options)
10+
offlinePage(workbox, options)
11+
routingExtensions(workbox, options)
12+
13+
function getProp(obj, prop) {
14+
return prop.split('.').reduce((p, c) => p[c], obj)
15+
}
16+
17+
function initWorkbox(workbox, options) {
18+
if (options.config) {
19+
// Set workbox config
20+
workbox.setConfig(options.config)
21+
}
22+
23+
if (options.cacheNames) {
24+
// Set workbox cache names
25+
workbox.core.setCacheNameDetails(options.cacheNames)
26+
}
27+
28+
if (options.clientsClaim) {
29+
// Start controlling any existing clients as soon as it activates
30+
workbox.core.clientsClaim()
31+
}
32+
33+
if (options.skipWaiting) {
34+
workbox.core.skipWaiting()
35+
}
36+
37+
if (options.cleanupOutdatedCaches) {
38+
workbox.precaching.cleanupOutdatedCaches()
39+
}
40+
41+
if (options.offlineAnalytics) {
42+
// Enable offline Google Analytics tracking
43+
workbox.googleAnalytics.initialize()
44+
}
45+
}
46+
47+
function precacheAssets(workbox, options) {
48+
if (options.preCaching.length) {
49+
workbox.precaching.precacheAndRoute(options.preCaching, options.cacheOptions)
50+
}
51+
}
52+
53+
54+
function runtimeCaching(workbox, options) {
55+
const requestInterceptor = {
56+
requestWillFetch({ request }) {
57+
if (request.cache === 'only-if-cached' && request.mode === 'no-cors') {
58+
return new Request(request.url, { ...request, cache: 'default', mode: 'no-cors' })
59+
}
60+
return request
61+
},
62+
fetchDidFail(ctx) {
63+
ctx.error.message =
64+
'[workbox] Network request for ' + ctx.request.url + ' threw an error: ' + ctx.error.message
65+
console.error(ctx.error, 'Details:', ctx)
66+
},
67+
handlerDidError(ctx) {
68+
ctx.error.message =
69+
`[workbox] Network handler threw an error: ` + ctx.error.message
70+
console.error(ctx.error, 'Details:', ctx)
71+
return null
72+
}
73+
}
74+
75+
for (const entry of options.runtimeCaching) {
76+
const urlPattern = new RegExp(entry.urlPattern)
77+
const method = entry.method || 'GET'
78+
79+
const plugins = (entry.strategyPlugins || [])
80+
.map(p => new (getProp(workbox, p.use))(...p.config))
81+
82+
plugins.unshift(requestInterceptor)
83+
84+
const strategyOptions = { ...entry.strategyOptions, plugins }
85+
86+
const strategy = new workbox.strategies[entry.handler](strategyOptions)
87+
88+
workbox.routing.registerRoute(urlPattern, strategy, method)
89+
}
90+
}
91+
92+
function offlinePage(workbox, options) {
93+
if (options.offlinePage) {
94+
// Register router handler for offlinePage
95+
workbox.routing.registerRoute(new RegExp(options.pagesURLPattern), ({ request, event }) => {
96+
const strategy = new workbox.strategies[options.offlineStrategy]
97+
return strategy
98+
.handle({ request, event })
99+
.catch(() => caches.match(options.offlinePage))
100+
})
101+
}
102+
}
103+
104+
function workboxExtensions(workbox, options) {
105+
106+
}
107+
108+
function cachingExtensions(workbox, options) {
109+
110+
}
111+
112+
function routingExtensions(workbox, options) {
113+
114+
}

packages/docs/static/sw.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// THIS FILE SHOULD NOT BE VERSION CONTROLLED
2+
3+
// https://github.com/NekR/self-destroying-sw
4+
5+
self.addEventListener('install', function (e) {
6+
self.skipWaiting()
7+
})
8+
9+
self.addEventListener('activate', function (e) {
10+
self.registration.unregister()
11+
.then(function () {
12+
return self.clients.matchAll()
13+
})
14+
.then(function (clients) {
15+
clients.forEach(client => client.navigate(client.url))
16+
})
17+
})
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
const ignorePaths = <%= serialize(options.ignorePaths) %>
2+
3+
<% if (options.loadFromFirebaseHosting) { %>
4+
// Only works on Firebase hosting!
5+
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js')
6+
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-auth-compat.js')
7+
importScripts('/__/firebase/init.js')
8+
<% } else { %>
9+
importScripts(
10+
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js'
11+
)
12+
importScripts(
13+
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-auth-compat.js'
14+
)
15+
firebase.initializeApp(<%= serialize(options.config) %>)
16+
<% } %>
17+
18+
// Initialize authService
19+
const authService = firebase.auth()
20+
21+
<% /* Uses emulator, if emulatorPort is set. */ %>
22+
<% const authOptions = options.authOptions %>
23+
<% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %>
24+
<% const emulatorHost =
25+
typeof authOptions.emulatorHost === 'string'
26+
? authOptions.emulatorHost
27+
: 'http://localhost'
28+
%>
29+
authService.useEmulator('<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>')
30+
<% } %>
31+
32+
33+
/**
34+
* Returns a promise that resolves with an ID token if available.
35+
* @return {!Promise<?string>} The promise that resolves with an ID token if
36+
* available. Otherwise, the promise resolves with null.
37+
*/
38+
const getIdToken = () => {
39+
return new Promise((resolve) => {
40+
const unsubscribe = authService.onAuthStateChanged((user) => {
41+
unsubscribe()
42+
if (user) {
43+
// force token refresh as it might be used to sign in server side
44+
user.getIdToken(true).then((idToken) => {
45+
resolve(idToken)
46+
}, () => {
47+
resolve(null)
48+
})
49+
} else {
50+
resolve(null)
51+
}
52+
})
53+
})
54+
}
55+
56+
const fetchWithAuthorization = async (original, idToken) => {
57+
// Clone headers as request headers are immutable.
58+
const headers = new Headers()
59+
for (let entry of original.headers.entries()) {
60+
headers.append(entry[0], entry[1])
61+
}
62+
63+
// Add ID token to header.
64+
headers.append('Authorization', 'Bearer ' + idToken)
65+
66+
// Create authorized request
67+
const { url, ...props } = original.clone()
68+
const authorized = new Request(url, {
69+
...props,
70+
mode: 'same-origin',
71+
redirect: 'manual',
72+
headers
73+
})
74+
75+
return fetch(authorized)
76+
}
77+
78+
self.addEventListener('fetch', (event) => {
79+
const url = new URL(event.request.url)
80+
81+
const expectsHTML = event.request.headers.get('accept').includes('text/html')
82+
83+
const isSameOrigin = self.location.origin === url.origin
84+
const isHttps = (self.location.protocol === 'https:' || self.location.hostname === 'localhost' || self.location.hostname === '127.0.0.1')
85+
86+
const isIgnored = ignorePaths.some(path => {
87+
if (typeof path === 'string') {
88+
return url.pathname.startsWith(path)
89+
}
90+
91+
return path.test(url.pathname.slice(1))
92+
})
93+
94+
// https://github.com/nuxt-community/firebase-module/issues/465
95+
if (!expectsHTML || !isSameOrigin || !isHttps || isIgnored) {
96+
<% if (['string', 'number'].includes(typeof authOptions.emulatorPort)) { %>
97+
<% const emulatorHost =
98+
typeof authOptions.emulatorHost === 'string'
99+
? authOptions.emulatorHost
100+
: 'http://localhost'
101+
%>
102+
if (event.request.url.startsWith('https://www.googleapis.com/identitytoolkit/')) {
103+
event.respondWith(
104+
fetch({
105+
...event.request,
106+
...{ url: event.request.url.replace(/https:\/\//, '<%= `${emulatorHost}` %>:<%= `${authOptions.emulatorPort}` %>/') }
107+
})
108+
)
109+
} else event.respondWith(fetch(event.request))
110+
<% } else { %>
111+
event.respondWith(fetch(event.request))
112+
<% } %>
113+
return
114+
}
115+
116+
117+
// Fetch the resource after checking for the ID token.
118+
// This can also be integrated with existing logic to serve cached files
119+
// in offline mode.
120+
event.respondWith(
121+
getIdToken().then(
122+
idToken => idToken
123+
// if the token was retrieved we attempt an authorized fetch
124+
// if anything goes wrong we fall back to the original request
125+
? fetchWithAuthorization(event.request, idToken).catch(() => fetch(event.request))
126+
// otherwise we return a fetch of the original request directly
127+
: fetch(event.request)
128+
)
129+
)
130+
})
131+
132+
// In service worker script.
133+
self.addEventListener('activate', event => {
134+
event.waitUntil(clients.claim())
135+
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<% if (options.loadFromFirebaseHosting) { %>
2+
// Only works on Firebase hosting & not on localhost!
3+
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-app-compat.js')
4+
importScripts('/__/firebase/<%= options.firebaseVersion %>/firebase-messaging-compat.js')
5+
importScripts('/__/firebase/init.js')
6+
<% } else { %>
7+
importScripts(
8+
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-app-compat.js'
9+
)
10+
importScripts(
11+
'https://www.gstatic.com/firebasejs/<%= options.firebaseVersion %>/firebase-messaging-compat.js'
12+
)
13+
firebase.initializeApp(<%= serialize(options.config) %>)
14+
<% } %>
15+
16+
// Retrieve an instance of Firebase Messaging so that it can handle background
17+
// messages.
18+
const messaging = firebase.messaging()
19+
20+
<% if (options.actions) { %>
21+
// Setup event listeners for actions provided in the config:
22+
self.addEventListener('notificationclick', function(e) {
23+
24+
const actions = <%= serialize(options.actions) %>
25+
const action = actions.find(x => x.action === e.action)
26+
const notification = e.notification
27+
28+
if (!action) return
29+
30+
if (action.url) {
31+
clients.openWindow(action.url)
32+
notification.close()
33+
}
34+
})
35+
<% } %>
36+
37+
<% if (options.inject) { %>
38+
<%= options.inject %>
39+
<% } %>

0 commit comments

Comments
 (0)