UNPKG

4.22 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8'use strict';
9
10var fs = require('fs');
11var path = require('path');
12var chalk = require('chalk');
13var filesize = require('filesize');
14var recursive = require('recursive-readdir');
15var stripAnsi = require('strip-ansi');
16var gzipSize = require('gzip-size').sync;
17
18// Prints a detailed summary of build files.
19function printFileSizesAfterBuild(
20 webpackStats,
21 previousSizeMap,
22 buildFolder,
23 maxBundleGzipSize,
24 maxChunkGzipSize
25) {
26 var root = previousSizeMap.root;
27 var sizes = previousSizeMap.sizes;
28 var assets = webpackStats
29 .toJson()
30 .assets.filter(asset => /\.(js|css)$/.test(asset.name))
31 .map(asset => {
32 var fileContents = fs.readFileSync(path.join(root, asset.name));
33 var size = gzipSize(fileContents);
34 var previousSize = sizes[removeFileNameHash(root, asset.name)];
35 var difference = getDifferenceLabel(size, previousSize);
36 return {
37 folder: path.join(path.basename(buildFolder), path.dirname(asset.name)),
38 name: path.basename(asset.name),
39 size: size,
40 sizeLabel: filesize(size) + (difference ? ' (' + difference + ')' : ''),
41 };
42 });
43 assets.sort((a, b) => b.size - a.size);
44 var longestSizeLabelLength = Math.max.apply(
45 null,
46 assets.map(a => stripAnsi(a.sizeLabel).length)
47 );
48 var suggestBundleSplitting = false;
49 assets.forEach(asset => {
50 var sizeLabel = asset.sizeLabel;
51 var sizeLength = stripAnsi(sizeLabel).length;
52 if (sizeLength < longestSizeLabelLength) {
53 var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength);
54 sizeLabel += rightPadding;
55 }
56 var isMainBundle = asset.name.indexOf('main.') === 0;
57 var maxRecommendedSize = isMainBundle
58 ? maxBundleGzipSize
59 : maxChunkGzipSize;
60 var isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
61 if (isLarge && path.extname(asset.name) === '.js') {
62 suggestBundleSplitting = true;
63 }
64 console.log(
65 ' ' +
66 (isLarge ? chalk.yellow(sizeLabel) : sizeLabel) +
67 ' ' +
68 chalk.dim(asset.folder + path.sep) +
69 chalk.cyan(asset.name)
70 );
71 });
72 if (suggestBundleSplitting) {
73 console.log();
74 console.log(
75 chalk.yellow('The bundle size is significantly larger than recommended.')
76 );
77 console.log(
78 chalk.yellow(
79 'Consider reducing it with code splitting: https://goo.gl/9VhYWB'
80 )
81 );
82 console.log(
83 chalk.yellow(
84 'You can also analyze the project dependencies: https://goo.gl/LeUzfb'
85 )
86 );
87 }
88}
89
90function removeFileNameHash(buildFolder, fileName) {
91 return fileName
92 .replace(buildFolder, '')
93 .replace(
94 /\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/,
95 (match, p1, p2, p3, p4) => p1 + p4
96 );
97}
98
99// Input: 1024, 2048
100// Output: "(+1 KB)"
101function getDifferenceLabel(currentSize, previousSize) {
102 var FIFTY_KILOBYTES = 1024 * 50;
103 var difference = currentSize - previousSize;
104 var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
105 if (difference >= FIFTY_KILOBYTES) {
106 return chalk.red('+' + fileSize);
107 } else if (difference < FIFTY_KILOBYTES && difference > 0) {
108 return chalk.yellow('+' + fileSize);
109 } else if (difference < 0) {
110 return chalk.green(fileSize);
111 } else {
112 return '';
113 }
114}
115
116function measureFileSizesBeforeBuild(buildFolder) {
117 return new Promise(resolve => {
118 recursive(buildFolder, (err, fileNames) => {
119 var sizes;
120 if (!err && fileNames) {
121 sizes = fileNames
122 .filter(fileName => /\.(js|css)$/.test(fileName))
123 .reduce((memo, fileName) => {
124 var contents = fs.readFileSync(fileName);
125 var key = removeFileNameHash(buildFolder, fileName);
126 memo[key] = gzipSize(contents);
127 return memo;
128 }, {});
129 }
130 resolve({
131 root: buildFolder,
132 sizes: sizes || {},
133 });
134 });
135 });
136}
137
138module.exports = {
139 measureFileSizesBeforeBuild: measureFileSizesBeforeBuild,
140 printFileSizesAfterBuild: printFileSizesAfterBuild,
141};