Skip to content

Commit 2b9f591

Browse files
committed
fix(externals): use resolver to resolve request
1 parent f145f6a commit 2b9f591

File tree

27 files changed

+310
-115
lines changed

27 files changed

+310
-115
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
},
6565
"pnpm": {
6666
"overrides": {
67+
"@rspack/core": "npm:@rspack/[email protected]",
6768
"zx>@types/node": "-"
6869
}
6970
}

packages/core/src/config.ts

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
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,
@@ -949,23 +951,37 @@ const composeBundleConfig = (
949951

950952
const isStyleRedirect = redirect.style ?? true;
951953

954+
type Resolver = GetAsyncFunctionFromUnion<
955+
ReturnType<NonNullable<Rspack.ExternalItemFunctionData['getResolve']>>
956+
>;
957+
let resolver: Resolver | undefined;
958+
952959
return {
953960
output: {
954961
externals: [
955-
(data: any, callback: any) => {
962+
async (data, callback) => {
963+
const { request, getResolve, context, contextInfo } = data;
964+
if (!request || !getResolve || !context || !contextInfo) {
965+
return callback();
966+
}
967+
968+
if (!resolver) {
969+
resolver = (await getResolve()) as Resolver;
970+
}
971+
956972
// Issuer is not empty string when the module is imported by another module.
957973
// Prevent from externalizing entry modules here.
958-
if (data.contextInfo.issuer) {
974+
if (contextInfo.issuer) {
959975
// Node.js ECMAScript module loader does no extension searching.
960976
// Add a file extension according to autoExtension config
961977
// when data.request is a relative path and do not have an extension.
962978
// If data.request already have an extension, we replace it with new extension
963979
// This may result in a change in semantics,
964980
// user should use copy to keep origin file or use another separate entry to deal this
965-
let request: string = data.request;
981+
let resolvedRequest: string = request;
966982

967983
const cssExternal = cssExternalHandler(
968-
request,
984+
resolvedRequest,
969985
callback,
970986
jsExtension,
971987
cssModulesAuto,
@@ -976,27 +992,40 @@ const composeBundleConfig = (
976992
return cssExternal;
977993
}
978994

979-
if (request[0] === '.') {
980-
const ext = extname(request);
995+
if (resolvedRequest[0] === '.') {
996+
const resolved = await resolver(context, resolvedRequest);
997+
resolvedRequest = path.posix.relative(
998+
path.dirname(contextInfo.issuer),
999+
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
};

packages/core/src/css/cssConfig.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function isCssGlobalFile(
7777
return !isCssModules;
7878
}
7979

80-
type ExternalCallback = (arg0?: null, arg1?: string) => void;
80+
type ExternalCallback = (arg0?: undefined, arg1?: string) => void;
8181

8282
export function cssExternalHandler(
8383
request: string,
@@ -99,12 +99,12 @@ export function cssExternalHandler(
9999
if (request[0] === '.' && isCssFile(request)) {
100100
// preserve import './CounterButton.module.scss'
101101
if (!isStyleRedirect) {
102-
return callback(null, request);
102+
return callback(undefined, request);
103103
}
104104
if (isCssModulesRequest) {
105-
return callback(null, request.replace(/\.[^.]+$/, jsExtension));
105+
return callback(undefined, request.replace(/\.[^.]+$/, jsExtension));
106106
}
107-
return callback(null, request.replace(/\.[^.]+$/, '.css'));
107+
return callback(undefined, request.replace(/\.[^.]+$/, '.css'));
108108
}
109109

110110
return false;

packages/core/src/types/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ export type DeepRequired<T> = Required<{
1212
}>;
1313

1414
export type ExcludesFalse = <T>(x: T | false | undefined | null) => x is T;
15+
16+
export type GetAsyncFunctionFromUnion<T> = T extends (
17+
...args: any[]
18+
) => Promise<any>
19+
? T
20+
: never;

0 commit comments

Comments
 (0)