Skip to content

Commit a43e933

Browse files
committed
fix(externals): use resolver to resolve request
1 parent aa4c5f3 commit a43e933

File tree

28 files changed

+342
-104
lines changed

28 files changed

+342
-104
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,
@@ -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
};

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
@@ -237,3 +237,8 @@ export const isIntermediateOutputFormat = (format: Format): boolean => {
237237
};
238238

239239
export { color };
240+
241+
const windowsSlashRegex = /\\/g;
242+
export function normalizeSlash(p: string): string {
243+
return p.replace(windowsSlashRegex, '/');
244+
}

0 commit comments

Comments
 (0)