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 ,
@@ -60,6 +62,7 @@ import {
6062 isEmptyObject ,
6163 isObject ,
6264 nodeBuiltInModules ,
65+ normalizeSlash ,
6366 omit ,
6467 pick ,
6568 readPackageJson ,
@@ -949,23 +952,37 @@ const composeBundleConfig = (
949952
950953 const isStyleRedirect = redirect . style ?? true ;
951954
955+ type Resolver = GetAsyncFunctionFromUnion <
956+ ReturnType < NonNullable < Rspack . ExternalItemFunctionData [ 'getResolve' ] > >
957+ > ;
958+ let resolver : Resolver | undefined ;
959+
952960 return {
953961 output : {
954962 externals : [
955- ( data : any , callback : any ) => {
963+ async ( data , callback ) => {
964+ const { request, getResolve, context, contextInfo } = data ;
965+ if ( ! request || ! getResolve || ! context || ! contextInfo ) {
966+ return callback ( ) ;
967+ }
968+
969+ if ( ! resolver ) {
970+ resolver = ( await getResolve ( ) ) as Resolver ;
971+ }
972+
956973 // Issuer is not empty string when the module is imported by another module.
957974 // Prevent from externalizing entry modules here.
958- if ( data . contextInfo . issuer ) {
975+ if ( contextInfo . issuer ) {
959976 // Node.js ECMAScript module loader does no extension searching.
960977 // Add a file extension according to autoExtension config
961978 // when data.request is a relative path and do not have an extension.
962979 // If data.request already have an extension, we replace it with new extension
963980 // This may result in a change in semantics,
964981 // user should use copy to keep origin file or use another separate entry to deal this
965- let request : string = data . request ;
982+ let resolvedRequest : string = request ;
966983
967984 const cssExternal = cssExternalHandler (
968- request ,
985+ resolvedRequest ,
969986 callback ,
970987 jsExtension ,
971988 cssModulesAuto ,
@@ -976,27 +993,39 @@ const composeBundleConfig = (
976993 return cssExternal ;
977994 }
978995
979- if ( request [ 0 ] === '.' ) {
980- const ext = extname ( request ) ;
996+ if ( resolvedRequest [ 0 ] === '.' ) {
997+ const resolved = await resolver ( context , resolvedRequest ) ;
998+ resolvedRequest = normalizeSlash (
999+ path . relative ( path . dirname ( contextInfo . issuer ) , resolved ) ,
1000+ ) ;
1001+
1002+ if ( resolvedRequest [ 0 ] !== '.' ) {
1003+ resolvedRequest = `./${ resolvedRequest } ` ;
1004+ }
1005+
1006+ const ext = extname ( resolvedRequest ) ;
9811007
9821008 if ( ext ) {
983- if ( JS_EXTENSIONS_PATTERN . test ( request ) ) {
984- request = request . replace ( / \. [ ^ . ] + $ / , jsExtension ) ;
1009+ if ( JS_EXTENSIONS_PATTERN . test ( resolvedRequest ) ) {
1010+ resolvedRequest = resolvedRequest . replace (
1011+ / \. [ ^ . ] + $ / ,
1012+ jsExtension ,
1013+ ) ;
9851014 } else {
9861015 // If it does not match jsExtensionsPattern, we should do nothing, eg: ./foo.png
9871016 return callback ( ) ;
9881017 }
9891018 } else {
9901019 // TODO: add redirect.extension option
991- request = `${ request } ${ jsExtension } ` ;
1020+ resolvedRequest = `${ resolvedRequest } ${ jsExtension } ` ;
9921021 }
9931022 }
9941023
995- return callback ( null , request ) ;
1024+ return callback ( undefined , resolvedRequest ) ;
9961025 }
9971026 callback ( ) ;
9981027 } ,
999- ] ,
1028+ ] as Rspack . ExternalItem [ ] ,
10001029 } ,
10011030 } ;
10021031} ;
0 commit comments