@@ -12,6 +12,7 @@ import { constants as fsConstants } from 'node:fs';
12
12
import fs from 'node:fs/promises' ;
13
13
import path from 'node:path' ;
14
14
import { BuildOutputFile } from '../../tools/esbuild/bundler-context' ;
15
+ import { BuildOutputAsset } from '../../tools/esbuild/bundler-execution-result' ;
15
16
import { buildApplicationInternal } from '../application' ;
16
17
import { Schema as ApplicationBuilderOptions } from '../application/schema' ;
17
18
import { logBuilderStatusWarnings } from './builder-status-warnings' ;
@@ -74,36 +75,61 @@ function normalizeOptions(options: BrowserBuilderOptions): ApplicationBuilderOpt
74
75
// and not output browser files into '/browser'.
75
76
async function writeResultFiles (
76
77
outputFiles : BuildOutputFile [ ] ,
77
- assetFiles : { source : string ; destination : string } [ ] | undefined ,
78
+ assetFiles : BuildOutputAsset [ ] | undefined ,
78
79
outputPath : string ,
79
80
) {
80
81
const directoryExists = new Set < string > ( ) ;
81
- await Promise . all (
82
- outputFiles . map ( async ( file ) => {
83
- // Ensure output subdirectories exist
84
- const basePath = path . dirname ( file . path ) ;
85
- if ( basePath && ! directoryExists . has ( basePath ) ) {
86
- await fs . mkdir ( path . join ( outputPath , basePath ) , { recursive : true } ) ;
87
- directoryExists . add ( basePath ) ;
88
- }
89
- // Write file contents
90
- await fs . writeFile ( path . join ( outputPath , file . path ) , file . contents ) ;
91
- } ) ,
92
- ) ;
82
+ const ensureDirectoryExists = async ( basePath : string ) => {
83
+ if ( basePath && ! directoryExists . has ( basePath ) ) {
84
+ await fs . mkdir ( path . join ( outputPath , basePath ) , { recursive : true } ) ;
85
+ directoryExists . add ( basePath ) ;
86
+ }
87
+ } ;
88
+
89
+ // Writes the output file to disk and ensures the containing directories are present
90
+ await emitFilesToDisk ( outputFiles , async ( file : BuildOutputFile ) => {
91
+ const fullOutputPath = file . fullOutputPath ;
92
+ // Ensure output subdirectories exist
93
+ const basePath = path . dirname ( fullOutputPath ) ;
94
+ await ensureDirectoryExists ( basePath ) ;
95
+
96
+ // Write file contents
97
+ await fs . writeFile ( path . join ( outputPath , fullOutputPath ) , file . contents ) ;
98
+ } ) ;
93
99
94
100
if ( assetFiles ?. length ) {
95
- await Promise . all (
96
- assetFiles . map ( async ( { source, destination } ) => {
97
- // Ensure output subdirectories exist
98
- const basePath = path . dirname ( destination ) ;
99
- if ( basePath && ! directoryExists . has ( basePath ) ) {
100
- await fs . mkdir ( path . join ( outputPath , basePath ) , { recursive : true } ) ;
101
- directoryExists . add ( basePath ) ;
102
- }
103
- // Copy file contents
104
- await fs . copyFile ( source , path . join ( outputPath ) , fsConstants . COPYFILE_FICLONE ) ;
105
- } ) ,
106
- ) ;
101
+ await emitFilesToDisk ( assetFiles , async ( asset : BuildOutputAsset ) => {
102
+ const destination = asset . destination ;
103
+ const basePath = path . dirname ( destination ) ;
104
+
105
+ // Ensure output subdirectories exist
106
+ await ensureDirectoryExists ( basePath ) ;
107
+
108
+ // Copy file contents
109
+ await fs . copyFile (
110
+ asset . source ,
111
+ path . join ( outputPath , destination ) ,
112
+ fsConstants . COPYFILE_FICLONE ,
113
+ ) ;
114
+ } ) ;
115
+ }
116
+ }
117
+
118
+ const MAX_CONCURRENT_WRITES = 64 ;
119
+ async function emitFilesToDisk < T = BuildOutputAsset | BuildOutputFile > (
120
+ files : T [ ] ,
121
+ writeFileCallback : ( asset : T ) => Promise < void > ,
122
+ ) : Promise < void > {
123
+ // Write files in groups of MAX_CONCURRENT_WRITES to avoid too many open files
124
+ for ( let fileIndex = 0 ; fileIndex < files . length ; ) {
125
+ const groupMax = Math . min ( fileIndex + MAX_CONCURRENT_WRITES , files . length ) ;
126
+
127
+ const actions = [ ] ;
128
+ while ( fileIndex < groupMax ) {
129
+ actions . push ( writeFileCallback ( files [ fileIndex ++ ] ) ) ;
130
+ }
131
+
132
+ await Promise . all ( actions ) ;
107
133
}
108
134
}
109
135
0 commit comments