WorkboxSW.mjs
5.39 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
import '../_version.mjs';
const CDN_PATH = `WORKBOX_CDN_ROOT_URL`;
const MODULE_KEY_TO_NAME_MAPPING = {
/**
* @name backgroundSync
* @memberof workbox
* @see module:workbox-background-sync
*/
backgroundSync: 'background-sync',
/**
* @name broadcastUpdate
* @memberof workbox
* @see module:workbox-broadcast-update
*/
broadcastUpdate: 'broadcast-update',
/**
* @name cacheableResponse
* @memberof workbox
* @see module:workbox-cacheable-response
*/
cacheableResponse: 'cacheable-response',
/**
* @name core
* @memberof workbox
* @see module:workbox-core
*/
core: 'core',
/**
* @name expiration
* @memberof workbox
* @see module:workbox-expiration
*/
expiration: 'expiration',
/**
* @name googleAnalytics
* @memberof workbox
* @see module:workbox-google-analytics
*/
googleAnalytics: 'offline-ga',
/**
* @name navigationPreload
* @memberof workbox
* @see module:workbox-navigation-preload
*/
navigationPreload: 'navigation-preload',
/**
* @name precaching
* @memberof workbox
* @see module:workbox-precaching
*/
precaching: 'precaching',
/**
* @name rangeRequests
* @memberof workbox
* @see module:workbox-range-requests
*/
rangeRequests: 'range-requests',
/**
* @name routing
* @memberof workbox
* @see module:workbox-routing
*/
routing: 'routing',
/**
* @name strategies
* @memberof workbox
* @see module:workbox-strategies
*/
strategies: 'strategies',
/**
* @name streams
* @memberof workbox
* @see module:workbox-streams
*/
streams: 'streams',
};
/**
* This class can be used to make it easy to use the various parts of
* Workbox.
*
* @private
*/
export class WorkboxSW {
/**
* Creates a proxy that automatically loads workbox namespaces on demand.
*
* @private
*/
constructor() {
this.v = {};
this._options = {
debug: self.location.hostname === 'localhost',
modulePathPrefix: null,
modulePathCb: null,
};
this._env = this._options.debug ? 'dev' : 'prod';
this._modulesLoaded = false;
return new Proxy(this, {
get(target, key) {
if (target[key]) {
return target[key];
}
const moduleName = MODULE_KEY_TO_NAME_MAPPING[key];
if (moduleName) {
target.loadModule(`workbox-${moduleName}`);
}
return target[key];
},
});
}
/**
* Updates the configuration options. You can specify whether to treat as a
* debug build and whether to use a CDN or a specific path when importing
* other workbox-modules
*
* @param {Object} [options]
* @param {boolean} [options.debug] If true, `dev` builds are using, otherwise
* `prod` builds are used. By default, `prod` is used unless on localhost.
* @param {Function} [options.modulePathPrefix] To avoid using the CDN with
* `workbox-sw` set the path prefix of where modules should be loaded from.
* For example `modulePathPrefix: '/third_party/workbox/v3.0.0/'`.
* @param {workbox~ModulePathCallback} [options.modulePathCb] If defined,
* this callback will be responsible for determining the path of each
* workbox module.
*
* @alias workbox.setConfig
*/
setConfig(options = {}) {
if (!this._modulesLoaded) {
Object.assign(this._options, options);
this._env = this._options.debug ? 'dev' : 'prod';
} else {
throw new Error('Config must be set before accessing workbox.* modules');
}
}
/**
* Load a Workbox module by passing in the appropriate module name.
*
* This is not generally needed unless you know there are modules that are
* dynamically used and you want to safe guard use of the module while the
* user may be offline.
*
* @param {string} moduleName
*
* @alias workbox.loadModule
*/
loadModule(moduleName) {
const modulePath = this._getImportPath(moduleName);
try {
importScripts(modulePath);
this._modulesLoaded = true;
} catch (err) {
// TODO Add context of this error if using the CDN vs the local file.
// We can't rely on workbox-core being loaded so using console
// eslint-disable-next-line
console.error(
`Unable to import module '${moduleName}' from '${modulePath}'.`);
throw err;
}
}
/**
* This method will get the path / CDN URL to be used for importScript calls.
*
* @param {string} moduleName
* @return {string} URL to the desired module.
*
* @private
*/
_getImportPath(moduleName) {
if (this._options.modulePathCb) {
return this._options.modulePathCb(moduleName, this._options.debug);
}
// TODO: This needs to be dynamic some how.
let pathParts = [CDN_PATH];
const fileName = `${moduleName}.${this._env}.js`;
const pathPrefix = this._options.modulePathPrefix;
if (pathPrefix) {
// Split to avoid issues with developers ending / not ending with slash
pathParts = pathPrefix.split('/');
// We don't need a slash at the end as we will be adding
// a filename regardless
if (pathParts[pathParts.length - 1] === '') {
pathParts.splice(pathParts.length - 1, 1);
}
}
pathParts.push(fileName);
return pathParts.join('/');
}
}