55 type RsbuildConfig ,
66 type RsbuildPlugin ,
77 type RsbuildPlugins ,
8+ type Rspack ,
89 defineConfig as defineRsbuildConfig ,
910 loadConfig as loadRsbuildConfig ,
1011 mergeRsbuildConfig ,
@@ -37,6 +38,7 @@ import type {
3738 DeepRequired ,
3839 ExcludesFalse ,
3940 Format ,
41+ GetAsyncFunctionFromUnion ,
4042 LibConfig ,
4143 LibOnlyConfig ,
4244 PkgJson ,
@@ -62,6 +64,7 @@ import {
6264 isIntermediateOutputFormat ,
6365 isObject ,
6466 nodeBuiltInModules ,
67+ normalizeSlash ,
6568 omit ,
6669 pick ,
6770 readPackageJson ,
@@ -965,23 +968,37 @@ const composeBundleConfig = (
965968
966969 const isStyleRedirect = redirect . style ?? true ;
967970
971+ type Resolver = GetAsyncFunctionFromUnion <
972+ ReturnType < NonNullable < Rspack . ExternalItemFunctionData [ 'getResolve' ] > >
973+ > ;
974+ let resolver : Resolver | undefined ;
975+
968976 return {
969977 output : {
970978 externals : [
971- ( data : any , callback : any ) => {
979+ async ( data , callback ) => {
980+ const { request, getResolve, context, contextInfo } = data ;
981+ if ( ! request || ! getResolve || ! context || ! contextInfo ) {
982+ return callback ( ) ;
983+ }
984+
985+ if ( ! resolver ) {
986+ resolver = ( await getResolve ( ) ) as Resolver ;
987+ }
988+
972989 // Issuer is not empty string when the module is imported by another module.
973990 // Prevent from externalizing entry modules here.
974- if ( data . contextInfo . issuer ) {
991+ if ( contextInfo . issuer ) {
975992 // Node.js ECMAScript module loader does no extension searching.
976993 // Add a file extension according to autoExtension config
977994 // when data.request is a relative path and do not have an extension.
978995 // If data.request already have an extension, we replace it with new extension
979996 // This may result in a change in semantics,
980997 // user should use copy to keep origin file or use another separate entry to deal this
981- let request : string = data . request ;
998+ let resolvedRequest : string = request ;
982999
9831000 const cssExternal = cssExternalHandler (
984- request ,
1001+ resolvedRequest ,
9851002 callback ,
9861003 jsExtension ,
9871004 cssModulesAuto ,
@@ -992,27 +1009,39 @@ const composeBundleConfig = (
9921009 return cssExternal ;
9931010 }
9941011
995- if ( request [ 0 ] === '.' ) {
996- const ext = extname ( request ) ;
1012+ if ( resolvedRequest [ 0 ] === '.' ) {
1013+ const resolved = await resolver ( context , resolvedRequest ) ;
1014+ resolvedRequest = normalizeSlash (
1015+ path . relative ( path . dirname ( contextInfo . issuer ) , resolved ) ,
1016+ ) ;
1017+
1018+ if ( resolvedRequest [ 0 ] !== '.' ) {
1019+ resolvedRequest = `./${ resolvedRequest } ` ;
1020+ }
1021+
1022+ const ext = extname ( resolvedRequest ) ;
9971023
9981024 if ( ext ) {
999- if ( JS_EXTENSIONS_PATTERN . test ( request ) ) {
1000- request = request . replace ( / \. [ ^ . ] + $ / , jsExtension ) ;
1025+ if ( JS_EXTENSIONS_PATTERN . test ( resolvedRequest ) ) {
1026+ resolvedRequest = resolvedRequest . replace (
1027+ / \. [ ^ . ] + $ / ,
1028+ jsExtension ,
1029+ ) ;
10011030 } else {
10021031 // If it does not match jsExtensionsPattern, we should do nothing, eg: ./foo.png
10031032 return callback ( ) ;
10041033 }
10051034 } else {
10061035 // TODO: add redirect.extension option
1007- request = `${ request } ${ jsExtension } ` ;
1036+ resolvedRequest = `${ resolvedRequest } ${ jsExtension } ` ;
10081037 }
10091038 }
10101039
1011- return callback ( null , request ) ;
1040+ return callback ( undefined , resolvedRequest ) ;
10121041 }
10131042 callback ( ) ;
10141043 } ,
1015- ] ,
1044+ ] as Rspack . ExternalItem [ ] ,
10161045 } ,
10171046 } ;
10181047} ;
0 commit comments