webpack-bundle-analyzer 2.8.1 → 2.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/LICENSE +1 -3
- package/README.md +9 -8
- package/lib/BundleAnalyzerPlugin.js +2 -6
- package/lib/analyzer.js +14 -20
- package/lib/parseUtils.js +11 -10
- package/lib/tree.js +47 -33
- package/lib/viewer.js +2 -6
- package/package.json +9 -8
- package/public/viewer.js +1 -1
- package/public/viewer.js.map +1 -1
- package/src/BundleAnalyzerPlugin.js +2 -6
- package/src/analyzer.js +13 -19
- package/src/parseUtils.js +11 -10
- package/src/tree.js +45 -30
- package/src/viewer.js +2 -6
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,31 @@
|
|
|
10
10
|
|
|
11
11
|
_Note: Gaps between patch versions are faulty, broken or test releases._
|
|
12
12
|
|
|
13
|
+
## 2.9.1
|
|
14
|
+
|
|
15
|
+
* **Bug Fix**
|
|
16
|
+
* Bump `ws` dependency to fix DoS vulnerability (closes [#130](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/130))
|
|
17
|
+
|
|
18
|
+
## 2.9.0
|
|
19
|
+
* **New Feature**
|
|
20
|
+
* Show chunk sizes in sidebar (closes #91)
|
|
21
|
+
|
|
22
|
+
* **Bug Fix**
|
|
23
|
+
* Properly parse webpack bundles that use arrow functions as module wrappers (#108, @regiontog)
|
|
24
|
+
|
|
25
|
+
## 2.8.3
|
|
26
|
+
* **Bug Fix**
|
|
27
|
+
* Correctly advertise port when using a random one (#89, @yannickcr)
|
|
28
|
+
* Add proper support for `multi` entries (fixes #92, #87)
|
|
29
|
+
* Support parsing of ESNext features (fixes #94)
|
|
30
|
+
|
|
31
|
+
## 2.8.2
|
|
32
|
+
* **Improvement**
|
|
33
|
+
* Greatly improved accuracy of gzip sizes
|
|
34
|
+
|
|
35
|
+
* **Bug Fix**
|
|
36
|
+
* Generate report file in the bundle output directory when used with Webpack Dev Server (fixes #75)
|
|
37
|
+
|
|
13
38
|
## 2.8.1
|
|
14
39
|
* **Improvement**
|
|
15
40
|
* Improve warning message when analyzer client couldn't connect to WebSocket server
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ command:
|
|
|
81
81
|
webpack --profile --json > stats.json
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
If you're on Windows and using PowerShell, you can generate the stats file with this command to [avoid BOM issues](https://github.com/
|
|
84
|
+
If you're on Windows and using PowerShell, you can generate the stats file with this command to [avoid BOM issues](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/47):
|
|
85
85
|
|
|
86
86
|
```
|
|
87
87
|
webpack --profile --json | Out-file 'stats.json' -Encoding OEM
|
|
@@ -108,14 +108,15 @@ as Uglify, then this value will reflect the minified size of your code.
|
|
|
108
108
|
|
|
109
109
|
### Gzip size
|
|
110
110
|
|
|
111
|
-
This is the size of running the file(s) through gzip compression.
|
|
112
|
-
value listed for the entire bundle is correct, but it will be slightly off if
|
|
113
|
-
you look at the gzip value for individual files.
|
|
111
|
+
This is the size of running the file(s) through gzip compression.
|
|
114
112
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
## Troubleshooting
|
|
114
|
+
|
|
115
|
+
### I can't see all the dependencies in a chunk
|
|
116
|
+
|
|
117
|
+
This is a known caveat when `webpack.optimize.ModuleConcatenationPlugin` is used. The way `ModuleConcatenationPlugin` works is that it merges multiple modules into a single one, and so that resulting module doesn't have edges anymore.
|
|
118
|
+
|
|
119
|
+
If you are interested to drill down to exact dependencies, try analyzing your bundle without `ModuleConcatenationPlugin`. See [issue #115](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/115) for more discussion.
|
|
119
120
|
|
|
120
121
|
## Contributing
|
|
121
122
|
|
|
@@ -85,11 +85,7 @@ var BundleAnalyzerPlugin = function () {
|
|
|
85
85
|
}, {
|
|
86
86
|
key: 'generateStatsFile',
|
|
87
87
|
value: function generateStatsFile(stats) {
|
|
88
|
-
var statsFilepath = this.opts.statsFilename;
|
|
89
|
-
|
|
90
|
-
if (!path.isAbsolute(statsFilepath)) {
|
|
91
|
-
statsFilepath = path.resolve(this.compiler.outputPath, statsFilepath);
|
|
92
|
-
}
|
|
88
|
+
var statsFilepath = path.resolve(this.compiler.outputPath, this.opts.statsFilename);
|
|
93
89
|
|
|
94
90
|
mkdir.sync(path.dirname(statsFilepath));
|
|
95
91
|
|
|
@@ -126,7 +122,7 @@ var BundleAnalyzerPlugin = function () {
|
|
|
126
122
|
value: function generateStaticReport(stats) {
|
|
127
123
|
viewer.generateReport(stats, {
|
|
128
124
|
openBrowser: this.opts.openAnalyzer,
|
|
129
|
-
reportFilename: this.opts.reportFilename,
|
|
125
|
+
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename),
|
|
130
126
|
bundleDir: this.getBundleDirFromCompiler(),
|
|
131
127
|
logger: this.logger,
|
|
132
128
|
defaultSizes: this.opts.defaultSizes
|
package/lib/analyzer.js
CHANGED
|
@@ -15,6 +15,7 @@ var _require2 = require('../lib/parseUtils'),
|
|
|
15
15
|
parseBundle = _require2.parseBundle;
|
|
16
16
|
|
|
17
17
|
var FILENAME_QUERY_REGEXP = /\?.*$/;
|
|
18
|
+
var MULTI_MODULE_REGEXP = /^multi /;
|
|
18
19
|
|
|
19
20
|
module.exports = {
|
|
20
21
|
getViewerData,
|
|
@@ -43,7 +44,6 @@ function getViewerData(bundleStats, bundleDir, opts) {
|
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
// Trying to parse bundle assets and get real module sizes if `bundleDir` is provided
|
|
46
|
-
var parsedModuleSizes = null;
|
|
47
47
|
var bundlesSources = null;
|
|
48
48
|
var parsedModules = null;
|
|
49
49
|
|
|
@@ -68,15 +68,15 @@ function getViewerData(bundleStats, bundleDir, opts) {
|
|
|
68
68
|
bundleInfo = null;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
if (bundleInfo) {
|
|
72
|
-
bundlesSources[statAsset.name] = bundleInfo.src;
|
|
73
|
-
_.assign(parsedModules, bundleInfo.modules);
|
|
74
|
-
} else {
|
|
71
|
+
if (!bundleInfo) {
|
|
75
72
|
logger.warn(`\nCouldn't parse bundle asset "${assetFile}".\n` + 'Analyzer will use module sizes from stats file.\n');
|
|
76
73
|
parsedModules = null;
|
|
77
74
|
bundlesSources = null;
|
|
78
75
|
break;
|
|
79
76
|
}
|
|
77
|
+
|
|
78
|
+
bundlesSources[statAsset.name] = bundleInfo.src;
|
|
79
|
+
_.assign(parsedModules, bundleInfo.modules);
|
|
80
80
|
}
|
|
81
81
|
} catch (err) {
|
|
82
82
|
_didIteratorError = true;
|
|
@@ -92,15 +92,6 @@ function getViewerData(bundleStats, bundleDir, opts) {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
|
|
96
|
-
if (parsedModules) {
|
|
97
|
-
parsedModuleSizes = _.mapValues(parsedModules, function (moduleSrc) {
|
|
98
|
-
return {
|
|
99
|
-
raw: moduleSrc.length,
|
|
100
|
-
gzip: gzipSize.sync(moduleSrc)
|
|
101
|
-
};
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
95
|
}
|
|
105
96
|
|
|
106
97
|
var assets = _.transform(bundleStats.assets, function (result, statAsset) {
|
|
@@ -115,9 +106,8 @@ function getViewerData(bundleStats, bundleDir, opts) {
|
|
|
115
106
|
asset.modules = _(bundleStats.modules).filter(function (statModule) {
|
|
116
107
|
return assetHasModule(statAsset, statModule);
|
|
117
108
|
}).each(function (statModule) {
|
|
118
|
-
if (
|
|
119
|
-
statModule.
|
|
120
|
-
statModule.gzipSize = parsedModuleSizes[statModule.id].gzip;
|
|
109
|
+
if (parsedModules) {
|
|
110
|
+
statModule.parsedSrc = parsedModules[statModule.id];
|
|
121
111
|
}
|
|
122
112
|
});
|
|
123
113
|
|
|
@@ -152,7 +142,7 @@ function createModulesTree(modules) {
|
|
|
152
142
|
var root = new Folder('.');
|
|
153
143
|
|
|
154
144
|
_.each(modules, function (module) {
|
|
155
|
-
var path = getModulePath(module
|
|
145
|
+
var path = getModulePath(module);
|
|
156
146
|
|
|
157
147
|
if (path) {
|
|
158
148
|
root.addModuleByPath(path, module);
|
|
@@ -162,10 +152,14 @@ function createModulesTree(modules) {
|
|
|
162
152
|
return root;
|
|
163
153
|
}
|
|
164
154
|
|
|
165
|
-
function getModulePath(
|
|
155
|
+
function getModulePath(module) {
|
|
156
|
+
if (MULTI_MODULE_REGEXP.test(module.identifier)) {
|
|
157
|
+
return [module.identifier];
|
|
158
|
+
}
|
|
159
|
+
|
|
166
160
|
var parsedPath = _
|
|
167
161
|
// Removing loaders from module path: they're joined by `!` and the last part is a raw module path
|
|
168
|
-
.last(
|
|
162
|
+
.last(module.name.split('!'))
|
|
169
163
|
// Splitting module path into parts
|
|
170
164
|
.split('/')
|
|
171
165
|
// Removing first `.`
|
package/lib/parseUtils.js
CHANGED
|
@@ -10,9 +10,14 @@ module.exports = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
function parseBundle(bundlePath) {
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
|
|
13
|
+
var content = fs.readFileSync(bundlePath, 'utf8');
|
|
14
|
+
var ast = acorn.parse(content, {
|
|
15
|
+
sourceType: 'script',
|
|
16
|
+
// I believe in a bright future of ECMAScript!
|
|
17
|
+
// Actually, it's set to `2050` to support the latest ECMAScript version that currently exists.
|
|
18
|
+
// Seems like `acorn` supports such weird option value.
|
|
19
|
+
ecmaVersion: 2050
|
|
20
|
+
});
|
|
16
21
|
|
|
17
22
|
var walkState = {
|
|
18
23
|
locations: null
|
|
@@ -63,9 +68,9 @@ function parseBundle(bundlePath) {
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
return {
|
|
66
|
-
src:
|
|
71
|
+
src: content,
|
|
67
72
|
modules: _.mapValues(walkState.locations, function (loc) {
|
|
68
|
-
return
|
|
73
|
+
return content.slice(loc.start, loc.end);
|
|
69
74
|
})
|
|
70
75
|
};
|
|
71
76
|
}
|
|
@@ -114,7 +119,7 @@ function isArgumentArrayConcatContainingChunks(arg) {
|
|
|
114
119
|
function isModuleWrapper(node) {
|
|
115
120
|
return (
|
|
116
121
|
// It's an anonymous function expression that wraps module
|
|
117
|
-
node.type === 'FunctionExpression' && !node.id ||
|
|
122
|
+
(node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') && !node.id ||
|
|
118
123
|
// If `DedupePlugin` is used it can be an ID of duplicated module...
|
|
119
124
|
isModuleId(node) ||
|
|
120
125
|
// or an array of shape [<module_id>, ...args]
|
|
@@ -171,9 +176,5 @@ function getModulesLocationFromArrayConcat(arg) {
|
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
function getModuleLocation(node) {
|
|
174
|
-
if (node.type === 'FunctionExpression') {
|
|
175
|
-
node = node.body;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
179
|
return _.pick(node, 'start', 'end');
|
|
179
180
|
}
|
package/lib/tree.js
CHANGED
|
@@ -12,6 +12,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
12
12
|
|
|
13
13
|
var _ = require('lodash');
|
|
14
14
|
var filesize = require('filesize');
|
|
15
|
+
var gzipSize = require('gzip-size');
|
|
15
16
|
|
|
16
17
|
var Node = function () {
|
|
17
18
|
function Node(name, parent) {
|
|
@@ -61,13 +62,13 @@ var Module = function (_Node) {
|
|
|
61
62
|
_createClass(Module, [{
|
|
62
63
|
key: 'mergeData',
|
|
63
64
|
value: function mergeData(data) {
|
|
64
|
-
|
|
65
|
+
if (data.size) {
|
|
66
|
+
this.size += data.size;
|
|
67
|
+
}
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
});
|
|
69
|
+
if (data.parsedSrc) {
|
|
70
|
+
this.src = (this.src || '') + data.parsedSrc;
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
}, {
|
|
73
74
|
key: 'toString',
|
|
@@ -86,20 +87,36 @@ var Module = function (_Node) {
|
|
|
86
87
|
gzipSize: this.gzipSize
|
|
87
88
|
};
|
|
88
89
|
}
|
|
90
|
+
}, {
|
|
91
|
+
key: 'src',
|
|
92
|
+
get: function get() {
|
|
93
|
+
return this.data.parsedSrc;
|
|
94
|
+
},
|
|
95
|
+
set: function set(value) {
|
|
96
|
+
this.data.parsedSrc = value;
|
|
97
|
+
delete this._gzipSize;
|
|
98
|
+
}
|
|
89
99
|
}, {
|
|
90
100
|
key: 'size',
|
|
91
101
|
get: function get() {
|
|
92
102
|
return this.data.size;
|
|
103
|
+
},
|
|
104
|
+
set: function set(value) {
|
|
105
|
+
this.data.size = value;
|
|
93
106
|
}
|
|
94
107
|
}, {
|
|
95
108
|
key: 'parsedSize',
|
|
96
109
|
get: function get() {
|
|
97
|
-
return this.
|
|
110
|
+
return this.src ? this.src.length : undefined;
|
|
98
111
|
}
|
|
99
112
|
}, {
|
|
100
113
|
key: 'gzipSize',
|
|
101
114
|
get: function get() {
|
|
102
|
-
|
|
115
|
+
if (!_.has(this, '_gzipSize')) {
|
|
116
|
+
this._gzipSize = this.src ? gzipSize.sync(this.src) : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this._gzipSize;
|
|
103
120
|
}
|
|
104
121
|
}]);
|
|
105
122
|
|
|
@@ -112,10 +129,10 @@ var Folder = function (_Node2) {
|
|
|
112
129
|
function Folder(name, parent) {
|
|
113
130
|
_classCallCheck(this, Folder);
|
|
114
131
|
|
|
115
|
-
var
|
|
132
|
+
var _this2 = _possibleConstructorReturn(this, (Folder.__proto__ || Object.getPrototypeOf(Folder)).call(this, name, parent));
|
|
116
133
|
|
|
117
|
-
|
|
118
|
-
return
|
|
134
|
+
_this2.children = Object.create(null);
|
|
135
|
+
return _this2;
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
_createClass(Folder, [{
|
|
@@ -130,7 +147,7 @@ var Folder = function (_Node2) {
|
|
|
130
147
|
|
|
131
148
|
this.children[name] = folder;
|
|
132
149
|
delete this._size;
|
|
133
|
-
delete this.
|
|
150
|
+
delete this._src;
|
|
134
151
|
|
|
135
152
|
return folder;
|
|
136
153
|
}
|
|
@@ -153,7 +170,7 @@ var Folder = function (_Node2) {
|
|
|
153
170
|
}
|
|
154
171
|
|
|
155
172
|
delete this._size;
|
|
156
|
-
delete this.
|
|
173
|
+
delete this._src;
|
|
157
174
|
|
|
158
175
|
return true;
|
|
159
176
|
}
|
|
@@ -189,11 +206,12 @@ var Folder = function (_Node2) {
|
|
|
189
206
|
key: 'walk',
|
|
190
207
|
value: function walk(walker) {
|
|
191
208
|
var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
209
|
+
var deep = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
192
210
|
|
|
193
211
|
var stopped = false;
|
|
194
212
|
|
|
195
213
|
_.each(this.children, function (child) {
|
|
196
|
-
if (child.walk) {
|
|
214
|
+
if (deep && child.walk) {
|
|
197
215
|
state = child.walk(walker, state, stop);
|
|
198
216
|
} else {
|
|
199
217
|
state = walker(child, state, stop);
|
|
@@ -237,13 +255,25 @@ var Folder = function (_Node2) {
|
|
|
237
255
|
groups: _.invokeMap(this.children, 'toChartData')
|
|
238
256
|
};
|
|
239
257
|
}
|
|
258
|
+
}, {
|
|
259
|
+
key: 'src',
|
|
260
|
+
get: function get() {
|
|
261
|
+
if (!_.has(this, '_src')) {
|
|
262
|
+
this._src = this.walk(function (node, src, stop) {
|
|
263
|
+
if (node.src === undefined) return stop(undefined);
|
|
264
|
+
return src += node.src;
|
|
265
|
+
}, '', false);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return this._src;
|
|
269
|
+
}
|
|
240
270
|
}, {
|
|
241
271
|
key: 'size',
|
|
242
272
|
get: function get() {
|
|
243
273
|
if (!_.has(this, '_size')) {
|
|
244
274
|
this._size = this.walk(function (node, size) {
|
|
245
275
|
return size + node.size;
|
|
246
|
-
}, 0);
|
|
276
|
+
}, 0, false);
|
|
247
277
|
}
|
|
248
278
|
|
|
249
279
|
return this._size;
|
|
@@ -251,29 +281,13 @@ var Folder = function (_Node2) {
|
|
|
251
281
|
}, {
|
|
252
282
|
key: 'parsedSize',
|
|
253
283
|
get: function get() {
|
|
254
|
-
|
|
255
|
-
this._parsedSize = this.walk(function (node, size, stop) {
|
|
256
|
-
if (node.parsedSize === undefined) {
|
|
257
|
-
return stop(undefined);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return size + node.parsedSize;
|
|
261
|
-
}, 0);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return this._parsedSize;
|
|
284
|
+
return this.src ? this.src.length : undefined;
|
|
265
285
|
}
|
|
266
286
|
}, {
|
|
267
287
|
key: 'gzipSize',
|
|
268
288
|
get: function get() {
|
|
269
289
|
if (!_.has(this, '_gzipSize')) {
|
|
270
|
-
this._gzipSize = this.
|
|
271
|
-
if (node.gzipSize === undefined) {
|
|
272
|
-
return stop(undefined);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return size + node.gzipSize;
|
|
276
|
-
}, 0);
|
|
290
|
+
this._gzipSize = this.src ? gzipSize.sync(this.src) : undefined;
|
|
277
291
|
}
|
|
278
292
|
|
|
279
293
|
return this._gzipSize;
|
package/lib/viewer.js
CHANGED
|
@@ -45,7 +45,7 @@ var startServer = function () {
|
|
|
45
45
|
server.listen(port, host, function () {
|
|
46
46
|
resolve();
|
|
47
47
|
|
|
48
|
-
var url = `http://${host}:${port}`;
|
|
48
|
+
var url = `http://${host}:${server.address().port}`;
|
|
49
49
|
|
|
50
50
|
logger.info(`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` + `Use ${bold('Ctrl+C')} to close it`);
|
|
51
51
|
|
|
@@ -139,11 +139,7 @@ function generateReport(bundleStats, opts) {
|
|
|
139
139
|
}, function (err, reportHtml) {
|
|
140
140
|
if (err) return logger.error(err);
|
|
141
141
|
|
|
142
|
-
var reportFilepath = reportFilename;
|
|
143
|
-
|
|
144
|
-
if (!path.isAbsolute(reportFilepath)) {
|
|
145
|
-
reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilepath);
|
|
146
|
-
}
|
|
142
|
+
var reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
|
|
147
143
|
|
|
148
144
|
mkdir.sync(path.dirname(reportFilepath));
|
|
149
145
|
fs.writeFileSync(reportFilepath, reportHtml);
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webpack-bundle-analyzer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "Webpack plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap",
|
|
5
5
|
"author": "Yury Grunin <grunin.ya@ya.ru>",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"homepage": "https://github.com/
|
|
8
|
-
"changelog": "https://github.com/
|
|
7
|
+
"homepage": "https://github.com/webpack-contrib/webpack-bundle-analyzer",
|
|
8
|
+
"changelog": "https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/master/CHANGELOG.md",
|
|
9
9
|
"bugs": {
|
|
10
|
-
"url": "https://github.com/
|
|
10
|
+
"url": "https://github.com/webpack-contrib/webpack-bundle-analyzer/issues"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/
|
|
14
|
+
"url": "git+https://github.com/webpack-contrib/webpack-bundle-analyzer.git"
|
|
15
15
|
},
|
|
16
16
|
"main": "lib/index.js",
|
|
17
17
|
"bin": "lib/bin/analyzer.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"views"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"acorn": "^5.
|
|
36
|
+
"acorn": "^5.1.1",
|
|
37
37
|
"chalk": "^1.1.3",
|
|
38
38
|
"commander": "^2.9.0",
|
|
39
39
|
"ejs": "^2.5.6",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"lodash": "^4.17.4",
|
|
44
44
|
"mkdirp": "^0.5.1",
|
|
45
45
|
"opener": "^1.4.3",
|
|
46
|
-
"ws": "^
|
|
46
|
+
"ws": "^3.3.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"babel-core": "6.24.1",
|
|
@@ -72,7 +72,8 @@
|
|
|
72
72
|
"sinon": "2.2.0",
|
|
73
73
|
"stream-combiner2": "1.1.1",
|
|
74
74
|
"style-loader": "0.17.0",
|
|
75
|
-
"webpack": "2.5.1"
|
|
75
|
+
"webpack": "2.5.1",
|
|
76
|
+
"webpack-dev-server": "2.4.5"
|
|
76
77
|
},
|
|
77
78
|
"keywords": [
|
|
78
79
|
"webpack",
|