UNPKG

3.9 kBJavaScriptView Raw
1'use strict';
2
3const EntryPoint = require('./entry-point');
4const Funnel = require('broccoli-funnel');
5const Rollup = require('./rollup-with-dependencies');
6const fs = require('fs');
7const mergeTrees = require('broccoli-merge-trees');
8const path = require('path');
9const rollupReplace = require('rollup-plugin-replace');
10const uglify = require('broccoli-uglify-sourcemap');
11
12const TREE_FOR_METHODS = {
13 'service-worker': 'treeForServiceWorker',
14 'service-worker-registration': 'treeForServiceWorkerRegistration'
15};
16
17module.exports = class ServiceWorkerBuilder {
18 constructor(options) {
19 this.options = options || {};
20
21 this.plugins = options.plugins;
22 this.appTree = options.appTree;
23 this.app = options.app;
24 }
25
26 build(type) {
27 let trees = this._treesForPlugins(type);
28 return this._compileTrees(trees, this._entryPointFilenameByType(type));
29 }
30
31 _treesForPlugins(type) {
32 return this.plugins.reduce((trees, plugin) => {
33 let pluginTree = this._treeForPlugin(plugin, type);
34
35 if (pluginTree) {
36 return trees.concat(pluginTree);
37 }
38
39 return trees
40 }, []);
41 }
42
43 _treeForPlugin(plugin, type) {
44 let pluginPath = path.resolve(plugin.root, type);
45 let treeForMethod = TREE_FOR_METHODS[type];
46
47 let tree;
48
49 if (fs.existsSync(pluginPath)) {
50 tree = this.app.treeGenerator(pluginPath);
51 }
52
53 if (plugin[treeForMethod]) {
54 tree = plugin[treeForMethod](tree, this.appTree);
55 }
56
57 if (tree) {
58 return new Funnel(tree, {
59 destDir: plugin.pkg.name + '/' + type
60 });
61 }
62 }
63
64 _compileTrees(trees, treeName) {
65 let entryPoint = new EntryPoint(trees, { entryPoint: `${treeName}` });
66 let tree = mergeTrees(trees.concat(entryPoint), { overwrite: true });
67
68 let registrationDistPath = this.options.registrationDistPath;
69 let treeDistPath = treeName;
70 if (treeName === 'sw-registration.js' && registrationDistPath) {
71 treeDistPath = path.join(registrationDistPath, treeName);
72 }
73
74 tree = this._babelTranspile(tree);
75 tree = this._rollupTree(tree, `${treeName}`, treeDistPath);
76 tree = this._uglifyTree(tree);
77
78 return tree;
79 }
80
81 _rollupTree(tree, entryFile, destFile) {
82 let rollupReplaceConfig = {
83 include: [
84 '/**/ember-service-worker/**/*.js',
85 // same as above but for windows paths like D:\my-ember\ember-service-worker\whatever\sw.js; which are updated before this step to D:/my-ember/ember-service/worker/whatever/sw.js
86 // the original one doesn't work when the source code and the %TMP% folder, which ember started to use after v3.5, are located on different logical drives
87 // which is quite common in Windows.
88 /^[a-z]:\/(?:[^\/:*?"<>|\r\n]+\/)*ember-service-worker\/(?:[^\/:*?"<>|\r\n]+\/)*[^\/:*?"<>|\r\n]*\.js$/i
89 ],
90 delimiters: ['{{', '}}'],
91 ROOT_URL: this.options.rootURL,
92 SERVICE_WORKER_FILENAME: this.options.serviceWorkerFilename
93 };
94
95 return new Rollup(tree, {
96 inputFiles: '**/*.js',
97 rollup: {
98 input: entryFile,
99 output: {
100 file: destFile || entryFile,
101 format: 'iife',
102 exports: 'none',
103 },
104 plugins: [
105 rollupReplace(rollupReplaceConfig)
106 ]
107 }
108 });
109 }
110
111 _uglifyTree(tree) {
112 if (this.options.minifyJS && this.options.minifyJS.enabled) {
113 let options = this.options.minifyJS.options || {};
114 options.sourceMapConfig = this.options.sourcemaps;
115 return uglify(tree, options);
116 }
117
118 return tree;
119 }
120
121 _babelTranspile(tree) {
122 let emberCliBabel = this.app.project.addons.filter((a) => a.name === 'ember-cli-babel')[0];
123 return emberCliBabel.transpileTree(tree, { 'ember-cli-babel': { compileModules: false } });
124 }
125
126 _entryPointFilenameByType(type) {
127 return type === 'service-worker' ? this.options.serviceWorkerFilename : 'sw-registration.js';
128 }
129}