44 type EnvironmentConfig ,
55 type RsbuildConfig ,
66 type RsbuildPlugin ,
7+ type Rspack ,
78 defineConfig as defineRsbuildConfig ,
89 loadConfig as loadRsbuildConfig ,
910 mergeRsbuildConfig ,
@@ -36,6 +37,7 @@ import type {
3637 DeepRequired ,
3738 ExcludesFalse ,
3839 Format ,
40+ GetAsyncFunctionFromUnion ,
3941 LibConfig ,
4042 LibOnlyConfig ,
4143 PkgJson ,
@@ -61,6 +63,7 @@ import {
6163 isIntermediateOutputFormat ,
6264 isObject ,
6365 nodeBuiltInModules ,
66+ normalizeSlash ,
6467 omit ,
6568 pick ,
6669 readPackageJson ,
@@ -963,23 +966,37 @@ const composeBundleConfig = (
963966
964967 const isStyleRedirect = redirect . style ?? true ;
965968
969+ type Resolver = GetAsyncFunctionFromUnion <
970+ ReturnType < NonNullable < Rspack . ExternalItemFunctionData [ 'getResolve' ] > >
971+ > ;
972+ let resolver : Resolver | undefined ;
973+
966974 return {
967975 output : {
968976 externals : [
969- ( data : any , callback : any ) => {
977+ async ( data , callback ) => {
978+ const { request, getResolve, context, contextInfo } = data ;
979+ if ( ! request || ! getResolve || ! context || ! contextInfo ) {
980+ return callback ( ) ;
981+ }
982+
983+ if ( ! resolver ) {
984+ resolver = ( await getResolve ( ) ) as Resolver ;
985+ }
986+
970987 // Issuer is not empty string when the module is imported by another module.
971988 // Prevent from externalizing entry modules here.
972- if ( data . contextInfo . issuer ) {
989+ if ( contextInfo . issuer ) {
973990 // Node.js ECMAScript module loader does no extension searching.
974991 // Add a file extension according to autoExtension config
975992 // when data.request is a relative path and do not have an extension.
976993 // If data.request already have an extension, we replace it with new extension
977994 // This may result in a change in semantics,
978995 // user should use copy to keep origin file or use another separate entry to deal this
979- let request : string = data . request ;
996+ let resolvedRequest : string = request ;
980997
981998 const cssExternal = cssExternalHandler (
982- request ,
999+ resolvedRequest ,
9831000 callback ,
9841001 jsExtension ,
9851002 cssModulesAuto ,
@@ -990,27 +1007,39 @@ const composeBundleConfig = (
9901007 return cssExternal ;
9911008 }
9921009
993- if ( request [ 0 ] === '.' ) {
994- const ext = extname ( request ) ;
1010+ if ( resolvedRequest [ 0 ] === '.' ) {
1011+ const resolved = await resolver ( context , resolvedRequest ) ;
1012+ resolvedRequest = normalizeSlash (
1013+ path . relative ( path . dirname ( contextInfo . issuer ) , resolved ) ,
1014+ ) ;
1015+
1016+ if ( resolvedRequest [ 0 ] !== '.' ) {
1017+ resolvedRequest = `./${ resolvedRequest } ` ;
1018+ }
1019+
1020+ const ext = extname ( resolvedRequest ) ;
9951021
9961022 if ( ext ) {
997- if ( JS_EXTENSIONS_PATTERN . test ( request ) ) {
998- request = request . replace ( / \. [ ^ . ] + $ / , jsExtension ) ;
1023+ if ( JS_EXTENSIONS_PATTERN . test ( resolvedRequest ) ) {
1024+ resolvedRequest = resolvedRequest . replace (
1025+ / \. [ ^ . ] + $ / ,
1026+ jsExtension ,
1027+ ) ;
9991028 } else {
10001029 // If it does not match jsExtensionsPattern, we should do nothing, eg: ./foo.png
10011030 return callback ( ) ;
10021031 }
10031032 } else {
10041033 // TODO: add redirect.extension option
1005- request = `${ request } ${ jsExtension } ` ;
1034+ resolvedRequest = `${ resolvedRequest } ${ jsExtension } ` ;
10061035 }
10071036 }
10081037
1009- return callback ( null , request ) ;
1038+ return callback ( undefined , resolvedRequest ) ;
10101039 }
10111040 callback ( ) ;
10121041 } ,
1013- ] ,
1042+ ] as Rspack . ExternalItem [ ] ,
10141043 } ,
10151044 } ;
10161045} ;
0 commit comments