@@ -275,8 +275,8 @@ export async function build(serverEntry?: string) {
275
275
}
276
276
tasks . push ( `${ alephPkgUri } /framework/core/nomodule.ts` ) ;
277
277
278
- const entryModules = new Set ( tasks ) ;
279
- const allModules = new Set < string > ( ) ;
278
+ const entryModules = new Map ( tasks . map ( ( task ) => [ task , 0 ] ) ) ;
279
+ const tracing = new Set < string > ( ) ;
280
280
281
281
// transform client modules
282
282
const serverHandler : FetchHandler | undefined = Reflect . get ( globalThis , "__ALEPH_SERVER" ) ?. handler ;
@@ -302,7 +302,7 @@ export async function build(serverEntry?: string) {
302
302
if ( ! isCSS ) {
303
303
clientDependencyGraph ?. get ( specifier ) ?. deps ?. forEach ( ( { specifier, dynamic } ) => {
304
304
if ( dynamic ) {
305
- entryModules . add ( specifier ) ;
305
+ entryModules . set ( specifier , 1 ) ;
306
306
}
307
307
if ( specifier . endsWith ( ".css" ) ) {
308
308
deps . add ( specifier + "?module" ) ;
@@ -313,15 +313,15 @@ export async function build(serverEntry?: string) {
313
313
} else if ( url . searchParams . has ( "module" ) ) {
314
314
deps . add ( `${ alephPkgUri } /framework/core/style.ts` ) ;
315
315
}
316
- allModules . add ( specifier ) ;
316
+ tracing . add ( specifier ) ;
317
317
} ) ) ;
318
- tasks = Array . from ( deps ) . filter ( ( specifier ) => ! allModules . has ( specifier ) ) ;
318
+ tasks = Array . from ( deps ) . filter ( ( specifier ) => ! tracing . has ( specifier ) ) ;
319
319
}
320
320
}
321
321
322
322
// count client module refs
323
323
const refs = new Map < string , Set < string > > ( ) ;
324
- for ( const name of entryModules ) {
324
+ for ( const [ name ] of entryModules ) {
325
325
clientDependencyGraph ?. walk ( name , ( { specifier } , importer ) => {
326
326
if ( importer ) {
327
327
let set = refs . get ( specifier ) ;
@@ -334,70 +334,47 @@ export async function build(serverEntry?: string) {
334
334
} ) ;
335
335
}
336
336
337
- // hygiene 1
338
- /*
339
- B(1) <-
340
- A <- <- <- D(1+) :: A <- D(1)
341
- C(1) <-
342
- */
343
- refs . forEach ( ( counter , specifier ) => {
337
+ const clientModules = new Map ( entryModules ) ;
338
+
339
+ // find shared modules
340
+ for ( const [ specifier , counter ] of refs ) {
344
341
if ( counter . size > 1 ) {
345
- const a = Array . from ( counter ) . filter ( ( specifier ) => {
346
- const set = refs . get ( specifier ) ;
347
- if ( set ?. size === 1 ) {
348
- const name = set . values ( ) . next ( ) . value ;
349
- if ( name && counter . has ( name ) ) {
350
- return false ;
351
- }
352
- }
353
- return true ;
354
- } ) ;
355
- refs . set ( specifier , new Set ( a ) ) ;
342
+ clientModules . set ( specifier , 2 ) ;
356
343
}
357
- } ) ;
344
+ }
358
345
359
- // hygiene 2 (twice)
360
- /*
361
- B(1) <-
362
- A <- C(1) <- E(1+) :: A <- E(1)
363
- D(1) <-
364
- */
365
- for ( let i = 0 ; i < 2 ; i ++ ) {
366
- refs . forEach ( ( counter , specifier ) => {
367
- if ( counter . size > 0 ) {
368
- const a = Array . from ( counter ) ;
369
- if ( a . every ( ( specifier ) => refs . get ( specifier ) ?. size === 1 ) ) {
370
- const set = new Set ( a . map ( ( specifier ) => refs . get ( specifier ) ?. values ( ) . next ( ) . value ) ) ;
371
- if ( set . size === 1 ) {
372
- refs . set ( specifier , set ) ;
346
+ // hygiene check, make sure all shared modules are not only referenced by other shared modules
347
+ for ( let i = 0 ; i < 100 ; i ++ ) {
348
+ const toHygiene = new Set < string > ( ) ;
349
+ for ( const [ specifier , type ] of clientModules ) {
350
+ if ( type === 2 ) {
351
+ const sharedBy = new Set < string > ( ) ;
352
+ clientDependencyGraph ?. lookup ( specifier , ( specifier ) => {
353
+ if ( clientModules . has ( specifier ) ) {
354
+ sharedBy . add ( specifier ) ;
355
+ return false ;
373
356
}
357
+ } ) ;
358
+ if ( sharedBy . size === 1 ) {
359
+ toHygiene . add ( specifier ) ;
374
360
}
375
361
}
376
- } ) ;
377
- }
378
-
379
- // find client modules
380
- const clientModules = new Set < string > ( entryModules ) ;
381
- refs . forEach ( ( counter , specifier ) => {
382
- if ( counter . size > 1 ) {
383
- clientModules . add ( specifier ) ;
384
362
}
385
- // console.log(`[${specifier}] \n - ${Array.from(counter).join("\n - ")}`);
386
- } ) ;
363
+ // break the loop when there are no more modules to hygiene
364
+ if ( toHygiene . size === 0 ) {
365
+ break ;
366
+ }
367
+ toHygiene . forEach ( ( specifier ) => clientModules . delete ( specifier ) ) ;
368
+ log . debug ( `hygiene#${ i + 1 } ` , toHygiene ) ;
369
+ }
387
370
388
371
// bundle client modules
389
- const bundling = new Set < string > ( ) ;
390
- clientModules . forEach ( ( specifier ) => {
391
- if (
392
- clientDependencyGraph ?. get ( specifier ) ?. deps ?. some ( ( { specifier } ) => ! clientModules . has ( specifier ) ) &&
393
- ! util . splitBy ( specifier , "?" ) [ 0 ] . endsWith ( ".css" )
394
- ) {
395
- bundling . add ( specifier ) ;
396
- }
397
- } ) ;
398
372
await Promise . all (
399
- Array . from ( bundling ) . map ( async ( entryPoint ) => {
373
+ Array . from ( clientModules . keys ( ) ) . map ( async ( entryPoint ) => {
400
374
const url = new URL ( util . isLikelyHttpURL ( entryPoint ) ? toLocalPath ( entryPoint ) : entryPoint , "http://localhost" ) ;
375
+ if ( url . pathname . endsWith ( ".css" ) ) {
376
+ return ;
377
+ }
401
378
let jsFile = join ( outputDir , url . pathname ) ;
402
379
if ( isEsmPkg ( entryPoint ) ) {
403
380
jsFile += ".js" ;
0 commit comments