@@ -918,76 +918,86 @@ const composeEntryConfig = async (
918918 } ;
919919 }
920920
921- // In bundleless mode, resolve glob patterns and convert them to entry object.
922- const resolvedEntries : Record < string , string > = { } ;
923- for ( const key of Object . keys ( entries ) ) {
924- const entry = entries [ key ] ;
925-
926- // Entries in bundleless mode could be:
927- // 1. A string of glob pattern: { entry: { index: 'src/*.ts' } }
928- // 2. An array of glob patterns: { entry: { index: ['src/*.ts', 'src/*.tsx'] } }
929- // Not supported for now: entry description object
930- const entryFiles = Array . isArray ( entry )
931- ? entry
932- : typeof entry === 'string'
933- ? [ entry ]
934- : null ;
935-
936- if ( ! entryFiles ) {
937- throw new Error (
938- 'Entry can only be a string or an array of strings for now' ,
939- ) ;
940- }
921+ const globScanEntries = async ( calcLcp : boolean ) => {
922+ // In bundleless mode, resolve glob patterns and convert them to entry object.
923+ const resolvedEntries : Record < string , string > = { } ;
924+ for ( const key of Object . keys ( entries ) ) {
925+ const entry = entries [ key ] ;
941926
942- // Turn entries in array into each separate entry.
943- const globEntryFiles = await glob ( entryFiles , {
944- cwd : root ,
945- absolute : true ,
946- } ) ;
927+ const entryFiles = Array . isArray ( entry )
928+ ? entry
929+ : typeof entry === 'string'
930+ ? [ entry ]
931+ : null ;
947932
948- // Filter the glob resolved entry files based on the allowed extensions
949- const resolvedEntryFiles = globEntryFiles . filter ( ( file ) =>
950- ENTRY_EXTENSIONS_PATTERN . test ( file ) ,
951- ) ;
933+ if ( ! entryFiles ) {
934+ throw new Error (
935+ 'Entry can only be a string or an array of strings for now' ,
936+ ) ;
937+ }
952938
953- if ( resolvedEntryFiles . length === 0 ) {
954- throw new Error ( `Cannot find ${ resolvedEntryFiles } ` ) ;
955- }
939+ // Turn entries in array into each separate entry.
940+ const globEntryFiles = await glob ( entryFiles , {
941+ cwd : root ,
942+ absolute : true ,
943+ } ) ;
956944
957- // Similar to `rootDir` in tsconfig and `outbase` in esbuild.
958- const lcp = await calcLongestCommonPath ( resolvedEntryFiles ) ;
959- // Using the longest common path of all non-declaration input files by default.
960- const outBase = lcp === null ? root : lcp ;
945+ // Filter the glob resolved entry files based on the allowed extensions
946+ const resolvedEntryFiles = globEntryFiles . filter ( ( file ) =>
947+ ENTRY_EXTENSIONS_PATTERN . test ( file ) ,
948+ ) ;
949+
950+ if ( resolvedEntryFiles . length === 0 ) {
951+ throw new Error ( `Cannot find ${ resolvedEntryFiles } ` ) ;
952+ }
961953
962- function getEntryName ( file : string ) {
963- const { dir , name } = path . parse ( path . relative ( outBase , file ) ) ;
964- // Entry filename contains nested path to preserve source directory structure .
965- const entryFileName = path . join ( dir , name ) ;
954+ // Similar to `rootDir` in tsconfig and `outbase` in esbuild.
955+ const lcp = await calcLongestCommonPath ( resolvedEntryFiles ) ;
956+ // Using the longest common path of all non-declaration input files by default .
957+ const outBase = lcp === null ? root : lcp ;
966958
967- // 1. we mark the global css files (which will generate empty js chunk in cssExtract), and deleteAsset in RemoveCssExtractAssetPlugin
968- // 2. avoid the same name e.g: `index.ts` and `index.css`
969- if ( isCssGlobalFile ( file , cssModulesAuto ) ) {
970- return `${ RSLIB_CSS_ENTRY_FLAG } /${ entryFileName } ` ;
959+ function getEntryName ( file : string ) {
960+ const { dir, name } = path . parse ( path . relative ( outBase , file ) ) ;
961+ // Entry filename contains nested path to preserve source directory structure.
962+ const entryFileName = path . join ( dir , name ) ;
963+
964+ // 1. we mark the global css files (which will generate empty js chunk in cssExtract), and deleteAsset in RemoveCssExtractAssetPlugin
965+ // 2. avoid the same name e.g: `index.ts` and `index.css`
966+ if ( isCssGlobalFile ( file , cssModulesAuto ) ) {
967+ return `${ RSLIB_CSS_ENTRY_FLAG } /${ entryFileName } ` ;
968+ }
969+
970+ return entryFileName ;
971971 }
972972
973- return entryFileName ;
973+ for ( const file of resolvedEntryFiles ) {
974+ const entryName = getEntryName ( file ) ;
975+ if ( resolvedEntries [ entryName ] ) {
976+ logger . warn (
977+ `duplicate entry: ${ entryName } , this may lead to the incorrect output, please rename the file` ,
978+ ) ;
979+ }
980+ resolvedEntries [ entryName ] = file ;
981+ }
974982 }
975983
976- for ( const file of resolvedEntryFiles ) {
977- const entryName = getEntryName ( file ) ;
978- if ( resolvedEntries [ entryName ] ) {
979- logger . warn (
980- `duplicate entry: ${ entryName } , this may lead to the incorrect output, please rename the file` ,
981- ) ;
982- }
983- resolvedEntries [ entryName ] = file ;
984+ if ( calcLcp ) {
985+ const lcp = await calcLongestCommonPath ( Object . values ( resolvedEntries ) ) ;
986+ return { resolvedEntries, lcp } ;
984987 }
985- }
988+ return { resolvedEntries, lcp : null } ;
989+ } ;
986990
987- const lcp = await calcLongestCommonPath ( Object . values ( resolvedEntries ) ) ;
991+ // LCP could only be determined at the first time of glob scan.
992+ const { lcp } = await globScanEntries ( true ) ;
988993 const entryConfig : EnvironmentConfig = {
989- source : {
990- entry : appendEntryQuery ( resolvedEntries ) ,
994+ tools : {
995+ rspack : {
996+ entry : async ( ) => {
997+ const { resolvedEntries } = await globScanEntries ( false ) ;
998+ return appendEntryQuery ( resolvedEntries ) ;
999+ } ,
1000+ } ,
9911001 } ,
9921002 } ;
9931003
@@ -1342,6 +1352,7 @@ async function composeLibRsbuildConfig(
13421352
13431353 const entryChunkConfig = composeEntryChunkConfig ( {
13441354 enabledImportMetaUrlShim : enabledShims . cjs [ 'import.meta.url' ] ,
1355+ contextToWatch : lcp ,
13451356 } ) ;
13461357 const dtsConfig = await composeDtsConfig ( config , dtsExtension ) ;
13471358 const externalsWarnConfig = composeExternalsWarnConfig (
0 commit comments