UNPKG

10.2 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true
5});
6
7var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8
9function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
10
11function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12
13var _webpackLibSingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
14
15var _webpackLibSingleEntryPlugin2 = _interopRequireDefault(_webpackLibSingleEntryPlugin);
16
17var _miscGetUglifyPlugin = require('./misc/get-uglify-plugin');
18
19var _miscGetUglifyPlugin2 = _interopRequireDefault(_miscGetUglifyPlugin);
20
21var _path = require('path');
22
23var _path2 = _interopRequireDefault(_path);
24
25var _deepExtend = require('deep-extend');
26
27var _deepExtend2 = _interopRequireDefault(_deepExtend);
28
29var _miscUtils = require('./misc/utils');
30
31var ServiceWorker = (function () {
32 function ServiceWorker(options) {
33 _classCallCheck(this, ServiceWorker);
34
35 if ((0, _miscUtils.isAbsolutePath)(options.output)) {
36 throw new Error('OfflinePlugin: ServiceWorker.output option must be a relative path, ' + 'but an absolute path was passed');
37 }
38
39 this.minify = options.minify;
40 this.output = options.output.replace(/^\.\/+/, '');
41 this.publicPath = options.publicPath;
42
43 this.basePath = null;
44 this.location = null;
45 this.pathRewrite = null;
46
47 // Tool specific properties
48 this.entry = options.entry;
49 this.scope = options.scope ? options.scope + '' : void 0;
50 this.events = !!options.events;
51 this.prefetchRequest = this.validatePrefetch(options.prefetchRequest);
52 this.updateViaCache = (options.updateViaCache || '') + '';
53 this.navigationPreload = options.navigationPreload;
54 this.forceInstall = !!options.forceInstall;
55
56 var cacheNameQualifier = '';
57
58 if (options.cacheName) {
59 cacheNameQualifier = ':' + options.cacheName;
60 }
61
62 this.ENTRY_NAME = 'serviceworker';
63 this.CACHE_NAME = 'webpack-offline' + cacheNameQualifier;
64 this.SW_DATA_VAR = '__wpo';
65 }
66
67 _createClass(ServiceWorker, [{
68 key: 'addEntry',
69 value: function addEntry(plugin, compilation, compiler) {
70 if (!this.entry) return Promise.resolve();
71
72 var name = plugin.entryPrefix + this.ENTRY_NAME;
73 var childCompiler = compilation.createChildCompiler(name, {
74 // filename: this.output
75 filename: name
76 });
77
78 var data = JSON.stringify({
79 data_var_name: this.SW_DATA_VAR,
80 cacheMaps: plugin.cacheMaps,
81 navigationPreload: this.stringifyNavigationPreload(this.navigationPreload, plugin)
82 });
83
84 var swLoaderPath = _path2['default'].join(__dirname, 'misc/sw-loader.js');
85 var loader = '!!' + swLoaderPath + '?json=' + escape(data);
86 var entry = loader + '!' + this.entry;
87
88 childCompiler.context = compiler.context;
89 new _webpackLibSingleEntryPlugin2['default'](compiler.context, entry, name).apply(childCompiler);
90
91 var optimization = compiler.options.optimization || {};
92
93 var uglifyOptions = {
94 compress: {
95 warnings: false,
96 dead_code: true,
97 drop_console: true,
98 unused: true
99 },
100
101 output: {
102 comments: false
103 }
104 };
105
106 if (this.minify === true) {
107 if (!_miscGetUglifyPlugin2['default']) {
108 throw new Error('OfflinePlugin: uglifyjs-webpack-plugin is required to preform a minification');
109 }
110
111 var options = {
112 test: new RegExp(name),
113 uglifyOptions: uglifyOptions
114 };
115
116 new _miscGetUglifyPlugin2['default'](options).apply(childCompiler);
117 } else if ((this.minify !== false || optimization.minimize) && _miscGetUglifyPlugin2['default']) {
118 // Do not perform auto-minification if UglifyJsPlugin isn't installed
119
120 var added = (optimization.minimize && optimization.minimizer || []).concat(compiler.options.plugins || []).some(function (plugin) {
121 if (plugin instanceof _miscGetUglifyPlugin2['default']) {
122 var options = (0, _deepExtend2['default'])({}, plugin.options);
123
124 options.test = new RegExp(name);
125 new _miscGetUglifyPlugin2['default'](options).apply(childCompiler);
126
127 return true;
128 }
129 });
130
131 if (!added && optimization.minimize) {
132 var options = {
133 test: new RegExp(name),
134 uglifyOptions: uglifyOptions
135 };
136
137 new _miscGetUglifyPlugin2['default'](options).apply(childCompiler);
138 }
139 }
140
141 // Needed for HMR. offline-plugin doesn't support it,
142 // but added just in case to prevent other errors
143 var compilationFn = function compilationFn(compilation) {
144 if (compilation.cache) {
145 if (!compilation.cache[name]) {
146 compilation.cache[name] = {};
147 }
148
149 compilation.cache = compilation.cache[name];
150 }
151 };
152
153 if (childCompiler.hooks) {
154 var _plugin = { name: 'OfflinePlugin' };
155 childCompiler.hooks.compilation.tap(_plugin, compilationFn);
156 } else {
157 childCompiler.plugin('compilation', compilationFn);
158 }
159
160 return new Promise(function (resolve, reject) {
161 childCompiler.runAsChild(function (err, entries, childCompilation) {
162 if (err) {
163 reject(err);
164 return;
165 }
166
167 resolve();
168 });
169 });
170 }
171 }, {
172 key: 'apply',
173 value: function apply(plugin, compilation, compiler) {
174 var minify = undefined;
175
176 if (typeof this.minify === 'boolean') {
177 minify = this.minify;
178 } else {
179 minify = !!_miscGetUglifyPlugin2['default'] && (!!(compiler.options.optimization && compiler.options.optimization.minimize) || !!(compiler.options.plugins || []).some(function (plugin) {
180 return plugin instanceof _miscGetUglifyPlugin2['default'];
181 }));
182 }
183
184 var source = this.getDataTemplate(plugin.caches, plugin, minify);
185
186 if (this.entry) {
187 var _name = plugin.entryPrefix + this.ENTRY_NAME;
188 var asset = compilation.assets[_name];
189
190 if (!asset) {
191 compilation.errors.push(new Error('OfflinePlugin: ServiceWorker entry is not found in output assets'));
192
193 return;
194 }
195
196 delete compilation.assets[_name];
197
198 if (!plugin.__tests.swMetadataOnly) {
199 source += '\n\n' + asset.source();
200 }
201 }
202
203 compilation.assets[this.output] = (0, _miscUtils.getSource)(source);
204 }
205 }, {
206 key: 'getDataTemplate',
207 value: function getDataTemplate(data, plugin, minify) {
208 var rewriteFunction = this.pathRewrite;
209
210 var cache = function cache(key) {
211 return (data[key] || []).map(rewriteFunction);
212 };
213
214 var hashesMap = Object.keys(plugin.hashesMap).reduce(function (result, hash) {
215 var asset = plugin.hashesMap[hash];
216
217 result[hash] = rewriteFunction(asset);
218 return result;
219 }, {});
220
221 var externals = plugin.externals.map(rewriteFunction);
222
223 var pluginVersion = undefined;
224
225 if (plugin.pluginVersion && !plugin.__tests.noVersionDump) {
226 pluginVersion = plugin.pluginVersion;
227 }
228
229 return ('\n var ' + this.SW_DATA_VAR + ' = ' + JSON.stringify({
230 assets: {
231 main: cache('main'),
232 additional: cache('additional'),
233 optional: cache('optional')
234 },
235
236 externals: externals,
237
238 hashesMap: hashesMap,
239
240 strategy: plugin.strategy,
241 responseStrategy: plugin.responseStrategy,
242 version: plugin.version,
243 name: this.CACHE_NAME,
244 pluginVersion: pluginVersion,
245 relativePaths: plugin.relativePaths,
246
247 prefetchRequest: this.prefetchRequest,
248
249 // These aren't added
250 alwaysRevalidate: plugin.alwaysRevalidate,
251 preferOnline: plugin.preferOnline,
252 ignoreSearch: plugin.ignoreSearch
253 }, null, minify ? void 0 : ' ') + ';\n ').trim();
254 }
255 }, {
256 key: 'getConfig',
257 value: function getConfig(plugin) {
258 return {
259 location: this.location,
260 scope: this.scope,
261 updateViaCache: this.updateViaCache,
262 events: this.events,
263 force: this.forceInstall
264 };
265 }
266 }, {
267 key: 'validatePrefetch',
268 value: function validatePrefetch(request) {
269 if (!request) {
270 return void 0;
271 }
272
273 if (request.credentials === 'same-origin' && request.headers === void 0 && request.mode === 'cors' && request.cache === void 0) {
274 return void 0;
275 }
276
277 return {
278 credentials: request.credentials,
279 headers: request.headers,
280 mode: request.mode,
281 cache: request.cache
282 };
283 }
284 }, {
285 key: 'stringifyNavigationPreload',
286 value: function stringifyNavigationPreload(navigationPreload, plugin) {
287 var result = undefined;
288
289 if (typeof navigationPreload === 'object') {
290 result = navigationPreload = '{\n map: ' + (0, _miscUtils.functionToString)(navigationPreload.map) + ',\n test: ' + (0, _miscUtils.functionToString)(navigationPreload.test) + '\n }';
291 } else {
292 if (typeof navigationPreload !== 'boolean') {
293 if (plugin.responseStrategy === 'network-first') {
294 navigationPreload = true;
295 } else {
296 navigationPreload = false;
297 }
298 }
299
300 result = JSON.stringify(navigationPreload);
301 }
302
303 return result;
304 }
305 }]);
306
307 return ServiceWorker;
308})();
309
310exports['default'] = ServiceWorker;
311module.exports = exports['default'];
\No newline at end of file