UNPKG

4.28 kBJavaScriptView Raw
1"use strict";
2
3const INDENT = 2;
4const DEFAULT_TRANSFORM = (data) => JSON.stringify(data, null, INDENT);
5
6/**
7 * Stats writer module.
8 *
9 * Stats can be a string or array (we'll have array due to source maps):
10 *
11 * ```js
12 * "assetsByChunkName": {
13 * "main": [
14 * "cd6371d4131fbfbefaa7.bundle.js",
15 * "../js-map/cd6371d4131fbfbefaa7.bundle.js.map"
16 * ]
17 * },
18 * ```
19 *
20 * **Note**: The stats object is **big**. It includes the entire source included
21 * in a bundle. Thus, we default `opts.fields` to `["assetsByChunkName"]` to
22 * only include those. However, if you want the _whole thing_ (maybe doing an
23 * `opts.transform` function), then you can set `fields: null` in options to
24 * get **all** of the stats object.
25 *
26 * You may also pass a custom stats config object (or string preset) via `opts.stats`
27 * in order to select exactly what you want added to the data passed to the transform.
28 * When `opts.stats` is passed, `opts.fields` will default to `null`.
29 *
30 * See:
31 * - https://webpack.js.org/configuration/stats/#stats
32 * - https://webpack.js.org/api/node/#stats-object
33 *
34 * **`filename`**: The `opts.filename` option can be a file name or path relative to
35 * `output.path` in webpack configuration. It should not be absolute.
36 *
37 * **`transform`**: By default, the retrieved stats object is `JSON.stringify`'ed
38 * but by supplying an alternate transform you can target _any_ output format.
39 * See [`test/webpack4/webpack.config.js`](test/webpack4/webpack.config.js) for
40 * various examples including Markdown output.
41 *
42 * - **Warning**: The output of `transform` should be a `String`, not an object.
43 * On Node `v4.x` if you return a real object in `transform`, then webpack
44 * will break with a `TypeError` (See #8). Just adding a simple
45 * `JSON.stringify()` around your object is usually what you need to solve
46 * any problems.
47 *
48 * @param {Object} opts options
49 * @param {String} opts.filename output file name (Default: `"stats.json`")
50 * @param {Array} opts.fields fields of stats obj to keep (Default: `["assetsByChunkName"]`)
51 * @param {Object|String} opts.stats stats config object or string preset (Default: `{}`)
52 * @param {Function|Promise} opts.transform transform stats obj (Default: `JSON.stringify()`)
53 *
54 * @api public
55 */
56class StatsWriterPlugin {
57 constructor(opts) {
58 opts = opts || {};
59 this.opts = {};
60 this.opts.filename = opts.filename || "stats.json";
61 this.opts.fields = typeof opts.fields !== "undefined" ? opts.fields : ["assetsByChunkName"];
62 this.opts.stats = opts.stats || {};
63 this.opts.transform = opts.transform || DEFAULT_TRANSFORM;
64
65 if (typeof opts.stats !== "undefined" && typeof opts.fields === "undefined") {
66 // if custom stats config provided, do not filter fields unless explicitly configured
67 this.opts.fields = null;
68 }
69 }
70
71 apply(compiler) {
72 if (compiler.hooks) {
73 compiler.hooks.emit.tapPromise("stats-writer-plugin", this.emitStats.bind(this));
74 } else {
75 compiler.plugin("emit", this.emitStats.bind(this));
76 }
77 }
78
79 emitStats(curCompiler, callback) {
80 // Get stats.
81 // The second argument automatically skips heavy options (reasons, source, etc)
82 // if they are otherwise unspecified.
83 let stats = curCompiler.getStats().toJson(this.opts.stats, "forToString");
84
85 // Filter to fields.
86 if (this.opts.fields) {
87 stats = this.opts.fields.reduce((memo, key) => {
88 memo[key] = stats[key];
89 return memo;
90 }, {});
91 }
92
93 // Transform to string.
94 let err;
95 return Promise.resolve()
96
97 // Transform.
98 .then(() => this.opts.transform(stats, {
99 compiler: curCompiler
100 }))
101 .catch((e) => { err = e; })
102
103 // Finish up.
104 .then((statsStr) => {
105 // Handle errors.
106 if (err) {
107 curCompiler.errors.push(err);
108 if (callback) { return void callback(err); }
109 throw err;
110 }
111
112 // Add to assets.
113 curCompiler.assets[this.opts.filename] = {
114 source() {
115 return statsStr;
116 },
117 size() {
118 return statsStr.length;
119 }
120 };
121
122 if (callback) { return void callback(); }
123 });
124 }
125}
126
127module.exports = StatsWriterPlugin;