@@ -12,7 +12,6 @@ import { createHash } from 'node:crypto';
12
12
import { constants as fsConstants } from 'node:fs' ;
13
13
import fs from 'node:fs/promises' ;
14
14
import path from 'node:path' ;
15
- import { promisify } from 'node:util' ;
16
15
import { brotliCompress } from 'node:zlib' ;
17
16
import { coerce } from 'semver' ;
18
17
import { NormalizedOutputOptions } from '../../builders/application/options' ;
@@ -22,8 +21,6 @@ import { BundleStats, generateBuildStatsTable } from '../webpack/utils/stats';
22
21
import { BuildOutputFile , BuildOutputFileType , InitialFileRecord } from './bundler-context' ;
23
22
import { BuildOutputAsset } from './bundler-execution-result' ;
24
23
25
- const compressAsync = promisify ( brotliCompress ) ;
26
-
27
24
export function logBuildStats (
28
25
context : BuilderContext ,
29
26
metafile : Metafile ,
@@ -87,31 +84,47 @@ export async function calculateEstimatedTransferSizes(
87
84
outputFiles : OutputFile [ ] ,
88
85
) : Promise < Map < string , number > > {
89
86
const sizes = new Map < string , number > ( ) ;
90
- const pendingCompression = [ ] ;
87
+ if ( outputFiles . length <= 0 ) {
88
+ return sizes ;
89
+ }
91
90
92
- for ( const outputFile of outputFiles ) {
93
- // Only calculate JavaScript and CSS files
94
- if ( ! outputFile . path . endsWith ( '.js' ) && ! outputFile . path . endsWith ( '.css' ) ) {
95
- continue ;
96
- }
91
+ return new Promise ( ( resolve , reject ) => {
92
+ let completeCount = 0 ;
93
+ for ( const outputFile of outputFiles ) {
94
+ // Only calculate JavaScript and CSS files
95
+ if ( ! outputFile . path . endsWith ( '.js' ) && ! outputFile . path . endsWith ( '.css' ) ) {
96
+ ++ completeCount ;
97
+ continue ;
98
+ }
97
99
98
- // Skip compressing small files which may end being larger once compressed and will most likely not be
99
- // compressed in actual transit.
100
- if ( outputFile . contents . byteLength < 1024 ) {
101
- sizes . set ( outputFile . path , outputFile . contents . byteLength ) ;
102
- continue ;
103
- }
100
+ // Skip compressing small files which may end being larger once compressed and will most likely not be
101
+ // compressed in actual transit.
102
+ if ( outputFile . contents . byteLength < 1024 ) {
103
+ sizes . set ( outputFile . path , outputFile . contents . byteLength ) ;
104
+ ++ completeCount ;
105
+ continue ;
106
+ }
104
107
105
- pendingCompression . push (
106
- compressAsync ( outputFile . contents ) . then ( ( result ) =>
107
- sizes . set ( outputFile . path , result . byteLength ) ,
108
- ) ,
109
- ) ;
110
- }
108
+ // Directly use the async callback function to minimize the number of Promises that need to be created.
109
+ brotliCompress ( outputFile . contents , ( error , result ) => {
110
+ if ( error ) {
111
+ reject ( error ) ;
111
112
112
- await Promise . all ( pendingCompression ) ;
113
+ return ;
114
+ }
113
115
114
- return sizes ;
116
+ sizes . set ( outputFile . path , result . byteLength ) ;
117
+ if ( ++ completeCount >= outputFiles . length ) {
118
+ resolve ( sizes ) ;
119
+ }
120
+ } ) ;
121
+ }
122
+
123
+ // Covers the case where no files need to be compressed
124
+ if ( completeCount >= outputFiles . length ) {
125
+ resolve ( sizes ) ;
126
+ }
127
+ } ) ;
115
128
}
116
129
117
130
export async function withSpinner < T > ( text : string , action : ( ) => T | Promise < T > ) : Promise < T > {
0 commit comments