@@ -15,11 +15,51 @@ export class InBrowserVite {
1515 private initialized = false ;
1616 private initPromise : Promise < void > | null = null ;
1717
18+ private async ensureEsbuildLoaded ( ) : Promise < void > {
19+ if ( ( window as any ) . esbuild ) {
20+ return ;
21+ }
22+
23+ const existingScript = document . querySelector ( 'script[src*="esbuild-wasm"]' ) ;
24+
25+ if ( existingScript ) {
26+ const maxRetries = 100 ;
27+ for ( let i = 0 ; i < maxRetries ; i ++ ) {
28+ if ( ( window as any ) . esbuild ) {
29+ return ;
30+ }
31+ await new Promise ( resolve => setTimeout ( resolve , 100 ) ) ;
32+ }
33+ console . warn ( '[InBrowserVite] Timeout waiting for existing script tag. Trying dynamic injection.' ) ;
34+ }
35+
36+ return new Promise ( ( resolve , reject ) => {
37+ if ( ( window as any ) . esbuild ) return resolve ( ) ;
38+
39+ const script = document . createElement ( 'script' ) ;
40+ script . src = "https://unpkg.com/esbuild-wasm@0.25.12/lib/browser.min.js" ;
41+ script . async = true ;
42+ script . onload = ( ) => {
43+ if ( ( window as any ) . esbuild ) {
44+ resolve ( ) ;
45+ } else {
46+ reject ( new Error ( 'Script loaded but window.esbuild is missing' ) ) ;
47+ }
48+ } ;
49+ script . onerror = ( ) => reject ( new Error ( 'Failed to load esbuild-wasm script from CDN' ) ) ;
50+ document . head . appendChild ( script ) ;
51+ } ) ;
52+ }
53+
1854 /**
1955 * Initialize esbuild-wasm. This is async and should be called before build.
2056 * Subsequent calls return the same initialization promise.
2157 */
2258 async initialize ( ) : Promise < void > {
59+ if ( this . initialized && this . esbuild ) {
60+ return ;
61+ }
62+
2363 if ( globalInitPromise ) {
2464 await globalInitPromise ;
2565 this . esbuild = globalEsbuild ;
@@ -29,22 +69,27 @@ export class InBrowserVite {
2969
3070 globalInitPromise = ( async ( ) => {
3171 try {
32- // @ts -ignore
33- if ( ! window . esbuild ) {
34- throw new Error ( 'esbuild not found on window. Make sure to include esbuild-wasm script.' ) ;
35- }
72+ await this . ensureEsbuildLoaded ( ) ;
73+
3674 const esbuild = ( window as any ) . esbuild ;
3775
38- await esbuild . initialize ( {
39- wasmURL : "https://unpkg.com/esbuild-wasm@0.25.12/esbuild.wasm" ,
40- worker : true ,
41- } ) ;
76+ try {
77+ await esbuild . initialize ( {
78+ wasmURL : "https://unpkg.com/esbuild-wasm@0.25.12/esbuild.wasm" ,
79+ worker : true ,
80+ } ) ;
81+ } catch ( initErr : any ) {
82+ if ( ! initErr . message . includes ( 'initialize' ) && ! initErr . message . includes ( 'already' ) ) {
83+ throw initErr ;
84+ }
85+ }
4286
4387 console . log ( '[InBrowserVite-LOG] ✅ esbuild initialized ' ) ;
4488 globalEsbuild = esbuild ;
4589
4690 } catch ( err ) {
4791 globalInitPromise = null ;
92+ console . error ( err ) ;
4893 throw new Error ( `esbuild initialization failed: ${ err . message } ` ) ;
4994 }
5095 } ) ( ) ;
@@ -69,11 +114,15 @@ export class InBrowserVite {
69114 */
70115 async build ( files : Map < string , string > , entry ?: string ) : Promise < BuildResult > {
71116 if ( ! this . isReady ( ) ) {
72- return {
73- js : '' ,
74- success : false ,
75- error : 'esbuild not initialized. Call initialize() first.' ,
76- } ;
117+ try {
118+ await this . initialize ( ) ;
119+ } catch ( e : any ) {
120+ return {
121+ js : '' ,
122+ success : false ,
123+ error : `Auto-initialization failed: ${ e . message } ` ,
124+ } ;
125+ }
77126 }
78127
79128 try {
0 commit comments