Skip to content

Commit 9df8ad7

Browse files
committed
fix: avoid chunk conflication when muliple libs present
1 parent f6981ca commit 9df8ad7

File tree

15 files changed

+310
-18
lines changed

15 files changed

+310
-18
lines changed

packages/core/src/config.ts

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -973,10 +973,11 @@ const composeExternalsConfig = (
973973
};
974974
};
975975

976-
const composeAutoExtensionConfig = (
976+
const composeOutputFilenameConfig = (
977977
config: LibConfig,
978978
format: Format,
979979
autoExtension: boolean,
980+
multiCompilerIndex: number | null,
980981
pkgJson?: PkgJson,
981982
): {
982983
config: EnvironmentConfig;
@@ -998,9 +999,38 @@ const composeAutoExtensionConfig = (
998999
return filenameHash ? '.[contenthash:8]' : '';
9991000
};
10001001

1002+
// Copied from https://github.com/web-infra-dev/rspack/blob/2efea8673f86a562559e26a9351680e8df4d9ae9/packages/rspack/src/config/defaults.ts#L667-L680.
1003+
const inferChunkFilename = (filename: string): string | undefined => {
1004+
if (typeof filename !== 'function') {
1005+
const hasName = filename.includes('[name]');
1006+
const hasId = filename.includes('[id]');
1007+
const hasChunkHash = filename.includes('[chunkhash]');
1008+
const hasContentHash = filename.includes('[contenthash]');
1009+
const multiCompilerPrefix =
1010+
typeof multiCompilerIndex === 'number' ? `${multiCompilerIndex}~` : '';
1011+
// Anything changing depending on chunk is fine
1012+
1013+
if (hasChunkHash || hasContentHash || hasName || hasId)
1014+
return filename.replace(
1015+
/(^|\/)([^/]*(?:\?|$))/,
1016+
`$1${multiCompilerPrefix}$2`,
1017+
);
1018+
// Otherwise prefix "[id]." in front of the basename to make it changing
1019+
return filename.replace(
1020+
/(^|\/)([^/]*(?:\?|$))/,
1021+
`$1${multiCompilerIndex}[id].$2`,
1022+
);
1023+
}
1024+
1025+
return undefined;
1026+
};
1027+
10011028
const hash = getHash();
10021029
const defaultJsFilename = `[name]${hash}${jsExtension}`;
10031030
const userJsFilename = config.output?.filename?.js;
1031+
const defaultJsChunkFilename = inferChunkFilename(
1032+
(userJsFilename as string) ?? defaultJsFilename,
1033+
);
10041034

10051035
// will be returned to use in redirect feature
10061036
// only support string type for now since we can not get the return value of function
@@ -1009,15 +1039,25 @@ const composeAutoExtensionConfig = (
10091039
? extname(userJsFilename)
10101040
: jsExtension;
10111041

1012-
const finalConfig = userJsFilename
1013-
? {}
1014-
: {
1042+
const chunkFilename: RsbuildConfig = {
1043+
tools: {
1044+
rspack: {
1045+
output: {
1046+
chunkFilename: defaultJsChunkFilename,
1047+
},
1048+
},
1049+
},
1050+
};
1051+
1052+
const finalConfig: RsbuildConfig = userJsFilename
1053+
? chunkFilename
1054+
: mergeRsbuildConfig(chunkFilename, {
10151055
output: {
10161056
filename: {
10171057
js: defaultJsFilename,
10181058
},
10191059
},
1020-
};
1060+
});
10211061

10221062
return {
10231063
config: finalConfig,
@@ -1604,6 +1644,7 @@ const composeExternalHelpersConfig = (
16041644

16051645
async function composeLibRsbuildConfig(
16061646
config: LibConfig,
1647+
multiCompilerIndex: number | null, // null means there's non multi-compiler
16071648
root?: string,
16081649
sharedPlugins?: RsbuildPlugins,
16091650
) {
@@ -1649,17 +1690,24 @@ async function composeLibRsbuildConfig(
16491690
config.output?.externals,
16501691
);
16511692
const {
1652-
config: autoExtensionConfig,
1693+
config: outputFilenameConfig,
16531694
jsExtension,
16541695
dtsExtension,
1655-
} = composeAutoExtensionConfig(config, format, autoExtension, pkgJson);
1696+
} = composeOutputFilenameConfig(
1697+
config,
1698+
format,
1699+
autoExtension,
1700+
multiCompilerIndex,
1701+
pkgJson,
1702+
);
16561703
const { entryConfig, outBase } = await composeEntryConfig(
16571704
config.source?.entry!,
16581705
config.bundle,
16591706
rootPath,
16601707
cssModulesAuto,
16611708
config.outBase,
16621709
);
1710+
16631711
const { config: bundlelessExternalConfig } = composeBundlelessExternalConfig(
16641712
jsExtension,
16651713
redirect,
@@ -1709,10 +1757,11 @@ async function composeLibRsbuildConfig(
17091757

17101758
return mergeRsbuildConfig(
17111759
formatConfig,
1760+
// outputConfig,
17121761
shimsConfig,
17131762
syntaxConfig,
17141763
externalHelpersConfig,
1715-
autoExtensionConfig,
1764+
outputFilenameConfig,
17161765
targetConfig,
17171766
// #region Externals configs
17181767
// The order of the externals config should come in the following order:
@@ -1761,7 +1810,7 @@ export async function composeCreateRsbuildConfig(
17611810
);
17621811
}
17631812

1764-
const libConfigPromises = libConfigsArray.map(async (libConfig) => {
1813+
const libConfigPromises = libConfigsArray.map(async (libConfig, index) => {
17651814
const userConfig = mergeRsbuildConfig<LibConfig>(
17661815
sharedRsbuildConfig,
17671816
libConfig,
@@ -1771,6 +1820,7 @@ export async function composeCreateRsbuildConfig(
17711820
// configuration and Lib configuration in the settings.
17721821
const libRsbuildConfig = await composeLibRsbuildConfig(
17731822
userConfig,
1823+
libConfigsArray.length > 1 ? index : null,
17741824
root,
17751825
sharedPlugins,
17761826
);

packages/core/tests/__snapshots__/config.test.ts.snap

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
393393
output: {
394394
path: '<WORKSPACE>/dist',
395395
filename: '[name].js',
396-
chunkFilename: '[name].js',
396+
chunkFilename: '0~[name].js',
397397
publicPath: 'auto',
398398
pathinfo: false,
399399
hashFunction: 'xxhash64',
@@ -1091,7 +1091,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
10911091
output: {
10921092
path: '<WORKSPACE>/dist',
10931093
filename: '[name].cjs',
1094-
chunkFilename: '[name].cjs',
1094+
chunkFilename: '1~[name].cjs',
10951095
publicPath: 'auto',
10961096
pathinfo: false,
10971097
hashFunction: 'xxhash64',
@@ -1775,7 +1775,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
17751775
output: {
17761776
path: '<WORKSPACE>/dist',
17771777
filename: '[name].js',
1778-
chunkFilename: '[name].js',
1778+
chunkFilename: '2~[name].js',
17791779
publicPath: '/',
17801780
pathinfo: false,
17811781
hashFunction: 'xxhash64',
@@ -2375,7 +2375,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
23752375
output: {
23762376
path: '<WORKSPACE>/dist',
23772377
filename: '[name].js',
2378-
chunkFilename: '[name].js',
2378+
chunkFilename: '3~[name].js',
23792379
publicPath: '/',
23802380
pathinfo: false,
23812381
hashFunction: 'xxhash64',
@@ -2918,7 +2918,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
29182918
output: {
29192919
path: '<WORKSPACE>/dist',
29202920
filename: '[name].js',
2921-
chunkFilename: '[name].js',
2921+
chunkFilename: '4~[name].js',
29222922
publicPath: '/',
29232923
pathinfo: false,
29242924
hashFunction: 'xxhash64',
@@ -3695,6 +3695,11 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
36953695
],
36963696
},
36973697
[Function],
3698+
{
3699+
"output": {
3700+
"chunkFilename": "0~[name].js",
3701+
},
3702+
},
36983703
{
36993704
"target": [
37003705
"node",
@@ -3966,6 +3971,11 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
39663971
],
39673972
},
39683973
[Function],
3974+
{
3975+
"output": {
3976+
"chunkFilename": "1~[name].cjs",
3977+
},
3978+
},
39693979
{
39703980
"target": [
39713981
"node",
@@ -4199,6 +4209,11 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
41994209
],
42004210
},
42014211
[Function],
4212+
{
4213+
"output": {
4214+
"chunkFilename": "2~[name].js",
4215+
},
4216+
},
42024217
{
42034218
"target": [
42044219
"node",
@@ -4431,6 +4446,11 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
44314446
],
44324447
},
44334448
[Function],
4449+
{
4450+
"output": {
4451+
"chunkFilename": "3~[name].js",
4452+
},
4453+
},
44344454
{
44354455
"target": [
44364456
"node",
@@ -4590,6 +4610,11 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
45904610
},
45914611
[Function],
45924612
[Function],
4613+
{
4614+
"output": {
4615+
"chunkFilename": "4~[name].js",
4616+
},
4617+
},
45934618
{
45944619
"target": [
45954620
"web",

pnpm-lock.yaml

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "minify-output-chunk-file-name-multi-test",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module"
6+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { defineConfig } from '@rslib/core';
2+
import { generateBundleEsmConfig } from 'test-helper';
3+
4+
export default defineConfig({
5+
lib: [
6+
generateBundleEsmConfig({
7+
source: {
8+
entry: {
9+
lib1: './src/lib1.js',
10+
},
11+
},
12+
}),
13+
generateBundleEsmConfig({
14+
source: {
15+
entry: {
16+
lib2: './src/lib2.js',
17+
},
18+
},
19+
}),
20+
],
21+
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { defineConfig } from '@rslib/core';
2+
import { generateBundleEsmConfig } from 'test-helper';
3+
4+
export default defineConfig({
5+
output: {
6+
filename: {
7+
js: 'static/js/[name].[contenthash:8].js',
8+
},
9+
},
10+
lib: [
11+
generateBundleEsmConfig({
12+
source: {
13+
entry: {
14+
lib1: './src/lib1.js',
15+
},
16+
},
17+
}),
18+
generateBundleEsmConfig({
19+
source: {
20+
entry: {
21+
lib2: './src/lib2.js',
22+
},
23+
},
24+
}),
25+
],
26+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { defineConfig } from '@rslib/core';
2+
import { generateBundleEsmConfig } from 'test-helper';
3+
4+
export default defineConfig({
5+
lib: [
6+
generateBundleEsmConfig({
7+
source: {
8+
entry: {
9+
lib1: './src/lib1.js',
10+
},
11+
},
12+
output: {
13+
filename: {
14+
js: 'static1/js/[name].js',
15+
},
16+
},
17+
}),
18+
generateBundleEsmConfig({
19+
source: {
20+
entry: {
21+
lib2: './src/lib2.js',
22+
},
23+
},
24+
output: {
25+
filename: {
26+
js: 'static2/js/[name].[contenthash:8].js',
27+
},
28+
},
29+
}),
30+
],
31+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default async function main() {
2+
const { foo } = await import('./shared.js');
3+
return foo;
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default async function main() {
2+
const { bar } = await import('./shared.js');
3+
return bar;
4+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const foo = 'foo';
2+
export const bar = 'bar';

0 commit comments

Comments
 (0)