UNPKG

4.99 kBJavaScriptView Raw
1'use strict';
2
3const ServiceWorkerBuilder = require('./lib/service-worker-builder');
4const InlineRegistration = require('./lib/inline-registration');
5const mergeTrees = require('broccoli-merge-trees');
6const writeFile = require('broccoli-file-creator');
7const hashForDep = require('hash-for-dep');
8const addonUtils = require('./lib/addon-utils');
9const IndexFile = require('./lib/index-file');
10
11module.exports = {
12 name: 'ember-service-worker',
13
14 included(app) {
15 if (this._super.included) {
16 this._super.included.apply(this, arguments);
17 }
18
19 // Configures Ember CLI's build system to not add a fingerprint to sw.js
20 this.app = app;
21 this.app.options = this.app.options || {};
22 let options = this.app.options['ember-service-worker'] = this.app.options['ember-service-worker'] || {}
23 options.serviceWorkerFilename = options.serviceWorkerFilename || 'sw.js';
24
25 this.app.options.fingerprint = this.app.options.fingerprint || {};
26 this.app.options.fingerprint.exclude = this.app.options.fingerprint.exclude || [];
27 this.app.options.fingerprint.exclude.push(options.serviceWorkerFilename);
28
29 options.registrationStrategy = options.registrationStrategy || 'default';
30
31 if (options.enabled === undefined) {
32 options.enabled = this.app.env !== 'test';
33 }
34
35 if (process.env.SW_DISABLED) {
36 options.enabled = false;
37 }
38
39 if (options.registrationStrategy === 'after-ember' && options.enabled !== false) {
40 app.import('vendor/ember-service-worker/load-registration-script.js');
41 }
42 },
43
44 treeForVendor() {
45 return writeFile('ember-service-worker/load-registration-script.js', `
46 (function() {
47 if (typeof FastBoot === 'undefined') {
48 var script = document.createElement('script')
49 script.src = '${this._getRootURL()}sw-registration.js';
50 document.body.appendChild(script);
51 }
52 })();
53 `);
54 },
55
56 postprocessTree(type, appTree) {
57 let options = this._getOptions();
58
59 if (type !== 'all' || options.enabled === false) {
60 return appTree;
61 }
62
63 let plugins = this._findPluginsFor(this.project);
64
65 // Add the project itself as a possible plugin, this way user can add custom
66 // service-worker code in their app, without needing to build a plugin.
67 plugins = [this].concat(plugins, this.project);
68
69 let serviceWorkerBuilder = new ServiceWorkerBuilder({
70 app: this,
71 appTree,
72 minifyJS: this.app.options.minifyJS,
73 fingerprint: this.app.options.fingerprint.enabled,
74 plugins,
75 rootURL: this._getRootURL(),
76 sourcemaps: this.app.options.sourcemaps,
77 registrationDistPath: options.registrationDistPath,
78 serviceWorkerFilename: options.serviceWorkerFilename
79 });
80
81 let serviceWorkerTree = serviceWorkerBuilder.build('service-worker');
82 let serviceWorkerRegistrationTree =
83 serviceWorkerBuilder.build('service-worker-registration');
84
85 if (options.registrationStrategy === 'inline') {
86 serviceWorkerRegistrationTree = new InlineRegistration([appTree, serviceWorkerRegistrationTree], options);
87 }
88
89 return mergeTrees([
90 appTree,
91 serviceWorkerTree,
92 serviceWorkerRegistrationTree
93 ], { overwrite: true });
94 },
95
96 contentFor(type, config) {
97 let options = this._getOptions();
98
99 if (options.enabled === false) {
100 return;
101 }
102
103 let registrationDistPath = options.registrationDistPath;
104 let srcPath = 'sw-registration.js';
105
106 if (registrationDistPath) {
107 srcPath = `${registrationDistPath}/${srcPath}`;
108 }
109
110 if (type === 'body-footer') {
111 if (options.registrationStrategy === 'default') {
112 return `<script src="${this._getRootURL()}${srcPath}"></script>`;
113 }
114
115 if (options.registrationStrategy === 'inline') {
116 return `<!-- ESW_INLINE_PLACEHOLDER -->`;
117 }
118 }
119
120 if (type === 'head-footer' && options.registrationStrategy === 'async') {
121 return `<script async src="${this._getRootURL()}${srcPath}"></script>`;
122 }
123 },
124
125 treeForServiceWorker(swTree, appTree) {
126 var options = this._getOptions();
127 options.projectVersion = this.project.pkg.version;
128
129 try {
130 options.projectRevision = hashForDep(this.project.root);
131 } catch (e) {
132 options.projectRevision = '0';
133 }
134
135 var indexFile = new IndexFile([appTree], options);
136
137 return mergeTrees([swTree, indexFile]);
138 },
139
140 _getRootURL() {
141 if (this._projectRootURL) {
142 return this._projectRootURL;
143 }
144
145 let options = this._getOptions();
146 let config = this._getConfig();
147 let rootURL = options.rootUrl || config.rootURL || config.baseURL || '/';
148
149 return this._projectRootURL = rootURL;
150 },
151
152 _getOptions() {
153 return this.app.options['ember-service-worker'];
154 },
155
156 _getConfig() {
157 return this.project.config(this.app.env);
158 },
159
160 _findPluginsFor(project) {
161 let addons = project.addons || [];
162 return addonUtils.filterByKeyword(addons, 'ember-service-worker-plugin');
163 }
164};