Skip to content

Commit

Permalink
fix(externals): use resolver to resolve request
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Dec 8, 2024
1 parent f145f6a commit 2b9f591
Show file tree
Hide file tree
Showing 27 changed files with 310 additions and 115 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
},
"pnpm": {
"overrides": {
"@rspack/core": "npm:@rspack/[email protected]",
"zx>@types/node": "-"
}
}
Expand Down
51 changes: 40 additions & 11 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type EnvironmentConfig,
type RsbuildConfig,
type RsbuildPlugin,
type Rspack,
defineConfig as defineRsbuildConfig,
loadConfig as loadRsbuildConfig,
mergeRsbuildConfig,
Expand Down Expand Up @@ -36,6 +37,7 @@ import type {
DeepRequired,
ExcludesFalse,
Format,
GetAsyncFunctionFromUnion,
LibConfig,
LibOnlyConfig,
PkgJson,
Expand Down Expand Up @@ -949,23 +951,37 @@ const composeBundleConfig = (

const isStyleRedirect = redirect.style ?? true;

type Resolver = GetAsyncFunctionFromUnion<
ReturnType<NonNullable<Rspack.ExternalItemFunctionData['getResolve']>>
>;
let resolver: Resolver | undefined;

return {
output: {
externals: [
(data: any, callback: any) => {
async (data, callback) => {
const { request, getResolve, context, contextInfo } = data;
if (!request || !getResolve || !context || !contextInfo) {
return callback();
}

if (!resolver) {
resolver = (await getResolve()) as Resolver;
}

// Issuer is not empty string when the module is imported by another module.
// Prevent from externalizing entry modules here.
if (data.contextInfo.issuer) {
if (contextInfo.issuer) {
// Node.js ECMAScript module loader does no extension searching.
// Add a file extension according to autoExtension config
// when data.request is a relative path and do not have an extension.
// If data.request already have an extension, we replace it with new extension
// This may result in a change in semantics,
// user should use copy to keep origin file or use another separate entry to deal this
let request: string = data.request;
let resolvedRequest: string = request;

const cssExternal = cssExternalHandler(
request,
resolvedRequest,
callback,
jsExtension,
cssModulesAuto,
Expand All @@ -976,27 +992,40 @@ const composeBundleConfig = (
return cssExternal;
}

if (request[0] === '.') {
const ext = extname(request);
if (resolvedRequest[0] === '.') {
const resolved = await resolver(context, resolvedRequest);
resolvedRequest = path.posix.relative(
path.dirname(contextInfo.issuer),
resolved,
);

if (resolvedRequest[0] !== '.') {
resolvedRequest = `./${resolvedRequest}`;
}

const ext = extname(resolvedRequest);

if (ext) {
if (JS_EXTENSIONS_PATTERN.test(request)) {
request = request.replace(/\.[^.]+$/, jsExtension);
if (JS_EXTENSIONS_PATTERN.test(resolvedRequest)) {
resolvedRequest = resolvedRequest.replace(
/\.[^.]+$/,
jsExtension,
);
} else {
// If it does not match jsExtensionsPattern, we should do nothing, eg: ./foo.png
return callback();
}
} else {
// TODO: add redirect.extension option
request = `${request}${jsExtension}`;
resolvedRequest = `${resolvedRequest}${jsExtension}`;
}
}

return callback(null, request);
return callback(undefined, resolvedRequest);
}
callback();
},
],
] as Rspack.ExternalItem[],
},
};
};
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/css/cssConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function isCssGlobalFile(
return !isCssModules;
}

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

export function cssExternalHandler(
request: string,
Expand All @@ -99,12 +99,12 @@ export function cssExternalHandler(
if (request[0] === '.' && isCssFile(request)) {
// preserve import './CounterButton.module.scss'
if (!isStyleRedirect) {
return callback(null, request);
return callback(undefined, request);
}
if (isCssModulesRequest) {
return callback(null, request.replace(/\.[^.]+$/, jsExtension));
return callback(undefined, request.replace(/\.[^.]+$/, jsExtension));
}
return callback(null, request.replace(/\.[^.]+$/, '.css'));
return callback(undefined, request.replace(/\.[^.]+$/, '.css'));
}

return false;
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ export type DeepRequired<T> = Required<{
}>;

export type ExcludesFalse = <T>(x: T | false | undefined | null) => x is T;

export type GetAsyncFunctionFromUnion<T> = T extends (
...args: any[]
) => Promise<any>
? T
: never;
Loading

0 comments on commit 2b9f591

Please sign in to comment.