Skip to content

Commit d28133f

Browse files
committed
fix(externals): use resolver to resolve request
1 parent 0f71812 commit d28133f

File tree

28 files changed

+505
-54
lines changed

28 files changed

+505
-54
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
@@ -5,6 +5,7 @@ import {
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
};

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;

packages/core/src/utils/helper.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,8 @@ export const isIntermediateOutputFormat = (format: Format): boolean => {
241241
};
242242

243243
export { color };
244+
245+
const windowsSlashRegex = /\\/g;
246+
export function normalizeSlash(p: string): string {
247+
return p.replace(windowsSlashRegex, '/');
248+
}

0 commit comments

Comments
 (0)