@@ -889,13 +889,14 @@ const composeEntryConfig = async (
889889 bundle : LibConfig [ 'bundle' ] ,
890890 root : string ,
891891 cssModulesAuto : CssLoaderOptionsAuto ,
892- ) : Promise < { entryConfig : EnvironmentConfig ; lcp : string | null } > => {
892+ userOutBase ?: string ,
893+ ) : Promise < { entryConfig : EnvironmentConfig ; outBase : string | null } > => {
893894 let entries : RsbuildConfigEntry = rawEntry ;
894895
895896 if ( ! entries ) {
896897 // In bundle mode, return directly to let Rsbuild apply default entry to './src/index.ts'
897898 if ( bundle !== false ) {
898- return { entryConfig : { } , lcp : null } ;
899+ return { entryConfig : { } , outBase : null } ;
899900 }
900901
901902 // In bundleless mode, set default entry to './src/**'
@@ -957,13 +958,26 @@ const composeEntryConfig = async (
957958 entry : appendEntryQuery ( resolveEntryPath ( entries , root ) ) ,
958959 } ,
959960 } ,
960- lcp : null ,
961+ outBase : null ,
961962 } ;
962963 }
963964
964- const scanGlobEntries = async ( calcLcp : boolean ) => {
965+ const scanGlobEntries = async ( tryResolveOutBase : boolean ) => {
965966 // In bundleless mode, resolve glob patterns and convert them to entry object.
966967 const resolvedEntries : Record < string , string > = { } ;
968+
969+ const resolveOutBase = async ( resolvedEntryFiles : string [ ] ) => {
970+ // Similar to `rootDir` in tsconfig and `outbase` in esbuild.
971+ const lcp = await calcLongestCommonPath ( resolvedEntryFiles ) ;
972+ // Using the longest common path of all non-declaration input files by default.
973+ const outBase = userOutBase
974+ ? path . resolve ( root , userOutBase )
975+ : lcp === null
976+ ? root
977+ : lcp ;
978+ return outBase ;
979+ } ;
980+
967981 for ( const key of Object . keys ( entries ) ) {
968982 const entry = entries [ key ] ;
969983
@@ -998,10 +1012,7 @@ const composeEntryConfig = async (
9981012 throw new Error ( `Cannot find ${ resolvedEntryFiles } ` ) ;
9991013 }
10001014
1001- // Similar to `rootDir` in tsconfig and `outbase` in esbuild.
1002- const lcp = await calcLongestCommonPath ( resolvedEntryFiles ) ;
1003- // Using the longest common path of all non-declaration input files by default.
1004- const outBase = lcp === null ? root : lcp ;
1015+ const outBase = await resolveOutBase ( resolvedEntryFiles ) ;
10051016
10061017 function getEntryName ( file : string ) {
10071018 const { dir, name } = path . parse ( path . relative ( outBase , file ) ) ;
@@ -1021,7 +1032,7 @@ const composeEntryConfig = async (
10211032 const entryName = getEntryName ( file ) ;
10221033
10231034 if ( resolvedEntries [ entryName ] ) {
1024- calcLcp &&
1035+ tryResolveOutBase &&
10251036 logger . warn (
10261037 `Duplicate entry ${ color . cyan ( entryName ) } from ${ color . cyan (
10271038 path . relative ( root , file ) ,
@@ -1035,15 +1046,15 @@ const composeEntryConfig = async (
10351046 }
10361047 }
10371048
1038- if ( calcLcp ) {
1039- const lcp = await calcLongestCommonPath ( Object . values ( resolvedEntries ) ) ;
1040- return { resolvedEntries, lcp } ;
1049+ if ( tryResolveOutBase ) {
1050+ const outBase = await resolveOutBase ( Object . values ( resolvedEntries ) ) ;
1051+ return { resolvedEntries, outBase } ;
10411052 }
1042- return { resolvedEntries, lcp : null } ;
1053+ return { resolvedEntries, outBase : null } ;
10431054 } ;
10441055
1045- // LCP could only be determined at the first time of glob scan.
1046- const { lcp } = await scanGlobEntries ( true ) ;
1056+ // OutBase could only be determined at the first time of glob scan.
1057+ const { outBase } = await scanGlobEntries ( true ) ;
10471058 const entryConfig : EnvironmentConfig = {
10481059 tools : {
10491060 rspack : {
@@ -1057,7 +1068,7 @@ const composeEntryConfig = async (
10571068
10581069 return {
10591070 entryConfig,
1060- lcp ,
1071+ outBase ,
10611072 } ;
10621073} ;
10631074
@@ -1415,14 +1426,15 @@ async function composeLibRsbuildConfig(
14151426 pkgJson,
14161427 userExternals : config . output ?. externals ,
14171428 } ) ;
1418- const { entryConfig, lcp } = await composeEntryConfig (
1429+ const { entryConfig, outBase } = await composeEntryConfig (
14191430 config . source ?. entry ! ,
14201431 config . bundle ,
14211432 rootPath ,
14221433 cssModulesAuto ,
1434+ config . outBase ,
14231435 ) ;
14241436 const cssConfig = composeCssConfig (
1425- lcp ,
1437+ outBase ,
14261438 config . bundle ,
14271439 banner ?. css ,
14281440 footer ?. css ,
@@ -1431,7 +1443,7 @@ async function composeLibRsbuildConfig(
14311443
14321444 const entryChunkConfig = composeEntryChunkConfig ( {
14331445 enabledImportMetaUrlShim : enabledShims . cjs [ 'import.meta.url' ] ,
1434- contextToWatch : lcp ,
1446+ contextToWatch : outBase ,
14351447 } ) ;
14361448 const dtsConfig = await composeDtsConfig ( config , dtsExtension ) ;
14371449 const externalsWarnConfig = composeExternalsWarnConfig (
@@ -1548,6 +1560,7 @@ export async function composeCreateRsbuildConfig(
15481560 dts : true ,
15491561 shims : true ,
15501562 umdName : true ,
1563+ outBase : true ,
15511564 } ) ,
15521565 ) ,
15531566 } ;
0 commit comments