@@ -23,6 +23,7 @@ import { sequencify } from '../utils/sequencify.ts';
2323import { Timing } from '../utils/timing.ts' ;
2424import { type ContextLoaderOptions , ContextLoader } from './context_loader.ts' ;
2525import { type FileLoaderOptions , CaseStyle , FULLPATH , FileLoader } from './file_loader.ts' ;
26+ import { ManifestStore , type StartupManifest } from './manifest.ts' ;
2627
2728const debug = debuglog ( 'egg/core/loader/egg_loader' ) ;
2829
@@ -47,6 +48,8 @@ export interface EggLoaderOptions {
4748 serverScope ?: string ;
4849 /** custom plugins */
4950 plugins ?: Record < string , EggPluginInfo > ;
51+ /** Skip lifecycle hooks, only trigger loadMetadata for manifest generation */
52+ metadataOnly ?: boolean ;
5053}
5154
5255export type EggDirInfoType = 'app' | 'plugin' | 'framework' ;
@@ -67,6 +70,8 @@ export class EggLoader {
6770 readonly appInfo : EggAppInfo ;
6871 readonly outDir ?: string ;
6972 dirs ?: EggDirInfo [ ] ;
73+ /** Startup manifest — loaded from cache or collecting for generation */
74+ readonly manifest : ManifestStore ;
7075
7176 /**
7277 * @class
@@ -154,6 +159,11 @@ export class EggLoader {
154159 * @since 1.0.0
155160 */
156161 this . appInfo = this . getAppInfo ( ) ;
162+
163+ // Load pre-computed manifest or create a collector for future generation
164+ this . manifest =
165+ ManifestStore . load ( this . options . baseDir , this . serverEnv , this . serverScope ) ??
166+ ManifestStore . createCollector ( this . options . baseDir ) ;
157167 }
158168
159169 get app ( ) : EggCore {
@@ -1233,15 +1243,23 @@ export class EggLoader {
12331243 */
12341244 async loadCustomApp ( ) : Promise < void > {
12351245 await this . #loadBootHook( 'app' ) ;
1236- this . lifecycle . triggerConfigWillLoad ( ) ;
1246+ if ( this . options . metadataOnly ) {
1247+ await this . lifecycle . triggerLoadMetadata ( ) ;
1248+ } else {
1249+ this . lifecycle . triggerConfigWillLoad ( ) ;
1250+ }
12371251 }
12381252
12391253 /**
12401254 * Load agent.js, same as {@link EggLoader#loadCustomApp}
12411255 */
12421256 async loadCustomAgent ( ) : Promise < void > {
12431257 await this . #loadBootHook( 'agent' ) ;
1244- this . lifecycle . triggerConfigWillLoad ( ) ;
1258+ if ( this . options . metadataOnly ) {
1259+ await this . lifecycle . triggerLoadMetadata ( ) ;
1260+ } else {
1261+ this . lifecycle . triggerConfigWillLoad ( ) ;
1262+ }
12451263 }
12461264
12471265 // FIXME: no logger used after egg removed
@@ -1627,6 +1645,7 @@ export class EggLoader {
16271645 directory : options ?. directory ?? directory ,
16281646 target,
16291647 inject : this . app ,
1648+ manifest : this . manifest ,
16301649 } ;
16311650
16321651 const timingKey = `Load "${ String ( property ) } " to Application` ;
@@ -1652,6 +1671,7 @@ export class EggLoader {
16521671 directory : options ?. directory || directory ,
16531672 property,
16541673 inject : this . app ,
1674+ manifest : this . manifest ,
16551675 } ;
16561676
16571677 const timingKey = `Load "${ String ( property ) } " to Context` ;
@@ -1688,11 +1708,15 @@ export class EggLoader {
16881708 }
16891709
16901710 resolveModule ( filepath : string ) : string | undefined {
1711+ return this . manifest . resolveModule ( filepath , ( ) => this . #doResolveModule( filepath ) ) ;
1712+ }
1713+
1714+ #doResolveModule( filepath : string ) : string | undefined {
16911715 let fullPath : string | undefined ;
16921716 try {
16931717 fullPath = utils . resolvePath ( filepath ) ;
16941718 } catch {
1695- // debug('[resolveModule] Module %o resolve error: %s', filepath, err.stack);
1719+ // ignore resolve errors
16961720 }
16971721 if ( ! fullPath ) {
16981722 fullPath = this . #resolveFromOutDir( filepath ) ;
@@ -1734,6 +1758,19 @@ export class EggLoader {
17341758 }
17351759 }
17361760 }
1761+
1762+ /**
1763+ * Generate startup manifest from collected data.
1764+ * Should be called after all loading phases complete.
1765+ */
1766+ generateManifest ( extensions ?: Record < string , unknown > ) : StartupManifest {
1767+ return this . manifest . generateManifest ( {
1768+ serverEnv : this . serverEnv ,
1769+ serverScope : this . serverScope ,
1770+ typescriptEnabled : isSupportTypeScript ( ) ,
1771+ extensions,
1772+ } ) ;
1773+ }
17371774}
17381775
17391776// convert dep to dependencies for compatibility
0 commit comments