@@ -108,10 +108,19 @@ export class BundlerCompilerService
108108 // HMR updates from. No-op unless bundler is vite + hmr + watch.
109109 // Fired in parallel with the build watcher; both child processes
110110 // inherit the adb-reverse env the run-controller set before
111- // prepare, so neither one spawns adb on its own. Intentionally not
112- // awaited — the device only connects to it at app launch, well
113- // after the first build.
114- this . startViteDevServer ( platformData , projectData , prepareData ) ;
111+ // prepare, so neither one spawns adb on its own. Not awaited HERE
112+ // — but the first-build resolution below gates on it, because the
113+ // app is (re)started as soon as `compileWithWatch` resolves and its
114+ // very first HTTP module fetch dies on connection-refused if the
115+ // server hasn't bound yet (a cold `vite serve` config load + vendor
116+ // prebuild competes with this build watcher for CPU and can take
117+ // 10-30s). Running both in parallel keeps the happy-path wall time
118+ // at max(first build, server bind) instead of their sum.
119+ const viteDevServerStartup = this . startViteDevServer (
120+ platformData ,
121+ projectData ,
122+ prepareData ,
123+ ) ;
115124
116125 try {
117126 const childProcess = await this . startBundleProcess (
@@ -183,15 +192,20 @@ export class BundlerCompilerService
183192 this . copyViteBundleToNative ( distOutput , destDir ) ;
184193 }
185194
186- // Resolve the promise on first build completion
195+ // Resolve the promise on first build completion — gated on
196+ // the HMR dev server being reachable (no-op resolve for
197+ // non-HMR runs). `startViteDevServer` never rejects and its
198+ // readiness probe is bounded, so this cannot hang the run;
199+ // on probe timeout we proceed and the device's own retry
200+ // handles any residual gap.
187201 if ( isFirstBundlerWatchCompilation ) {
188202 isFirstBundlerWatchCompilation = false ;
189203 if ( debugLog ) {
190204 console . log (
191205 "Vite first build completed, resolving compileWithWatch" ,
192206 ) ;
193207 }
194- resolve ( childProcess ) ;
208+ viteDevServerStartup . then ( ( ) => resolve ( childProcess ) ) ;
195209 return ;
196210 }
197211
@@ -703,7 +717,11 @@ export class BundlerCompilerService
703717 `Vite dev server ready on port ${ port } (HMR for ${ key } ).` ,
704718 ) ;
705719 } else {
706- this . $logger . trace (
720+ // Warn (not trace): the first-build resolution in
721+ // `compileWithWatch` gates on this method, so a probe timeout
722+ // means the app will be deployed against a server that may not
723+ // be up yet — the user should see why a boot might stall.
724+ this . $logger . warn (
707725 `Vite dev server port ${ port } not observed open within the readiness probe window; continuing (it may bind shortly).` ,
708726 ) ;
709727 }
0 commit comments