Skip to content

Commit

Permalink
feat: split chunks overall filename (#9243)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk authored Feb 11, 2025
1 parent 38fbd20 commit d688f4d
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 57 deletions.
1 change: 1 addition & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,7 @@ export interface RawSplitChunkSizes {
export interface RawSplitChunksOptions {
fallbackCacheGroup?: RawFallbackCacheGroupOptions
name?: string | false | Function
filename?: JsFilename
cacheGroups?: Array<RawCacheGroupOptions>
/** What kind of chunks should be selected. */
chunks?: RegExp | 'async' | 'initial' | 'all' | Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct RawSplitChunksOptions {
#[napi(ts_type = "string | false | Function")]
#[debug(skip)]
pub name: Option<RawChunkOptionName>,
pub filename: Option<JsFilename>,
pub cache_groups: Option<Vec<RawCacheGroupOptions>>,
/// What kind of chunks should be selected.
#[napi(ts_type = "RegExp | 'async' | 'initial' | 'all' | Function")]
Expand Down Expand Up @@ -107,6 +108,8 @@ impl From<RawSplitChunksOptions> for rspack_plugin_split_chunks::PluginOptions {

let mut cache_groups = vec![];

let overall_filename = raw_opts.filename.map(Filename::from);

let overall_chunk_filter = raw_opts.chunks.map(create_chunks_filter);

let overall_min_chunks = raw_opts.min_chunks.unwrap_or(1);
Expand Down Expand Up @@ -214,7 +217,10 @@ impl From<RawSplitChunksOptions> for rspack_plugin_split_chunks::PluginOptions {
automatic_name_delimiter: v
.automatic_name_delimiter
.unwrap_or(overall_automatic_name_delimiter.clone()),
filename: v.filename.map(Filename::from),
filename: v
.filename
.map(Filename::from)
.or_else(|| overall_filename.clone()),
reuse_existing_chunk: v.reuse_existing_chunk.unwrap_or(false),
max_async_requests: v.max_async_requests.unwrap_or(f64::INFINITY),
max_initial_requests: v.max_initial_requests.unwrap_or(f64::INFINITY),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "./shared1";
import "./common1";

it("should be able to load the split chunk on demand (shared)", () => {
return import(/* webpackChunkName: "theName" */ "./shared2");
});

it("should be able to load the split chunk on demand (common)", () => {
return Promise.all([
import(/* webpackChunkName: "otherName1" */ "./common2"),
import(/* webpackChunkName: "otherName2" */ "./common3")
]);
});

it("should have files", async () => {
const fs = require("fs");
const path = require("path");
const files = await fs.promises.readdir(__dirname);
expect(files).toContain("shared-shared-shared1_js.js");
expect(files).toContain("shared-shared-shared2_js.js");
expect(files).toContain("splitted-chunks");
const innerFiles = await fs.promises.readdir(path.resolve(__dirname, "splitted-chunks"));
expect(innerFiles).toContain("common-common1_js.js");
expect(innerFiles).toContain("common-common2_js.js");
expect(innerFiles).toContain("common-common3_js.js");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import "./shared1";
import "./shared2";
import "./common1";
import "./common2";
import "./common3";
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/** @type {import("@rspack/core").Configuration} */
module.exports = {
mode: "development",
entry: {
a: "./a",
b: "./b"
},
output: {
filename: "[name].js",
libraryTarget: "commonjs2"
},
optimization: {
chunkIds: "named",
splitChunks: {
filename: "splitted-chunks/[name].js",
cacheGroups: {
shared: {
chunks: "all",
test: /shared/,
filename: "shared-[name].js",
enforce: true
},
common: {
chunks: "all",
test: /common/,
enforce: true
}
}
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import("../../../..").TConfigCaseConfig} */
module.exports = {
findBundle: function (i, options) {
return ["a.js"];
}
};
11 changes: 9 additions & 2 deletions packages/rspack/etc/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4260,7 +4260,6 @@ export type OptimizationSplitChunksCacheGroup = {
test?: string | RegExp | ((module: Module) => unknown);
priority?: number;
enforce?: boolean;
filename?: Filename;
reuseExistingChunk?: boolean;
type?: string | RegExp;
idHint?: string;
Expand Down Expand Up @@ -7147,6 +7146,7 @@ export const rspackOptions: z.ZodObject<{
minChunks: z.ZodOptional<z.ZodNumber>;
usedExports: z.ZodOptional<z.ZodBoolean>;
name: z.ZodOptional<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodLiteral<false>]>, z.ZodFunction<z.ZodTuple<[z.ZodType<Module, z.ZodTypeDef, Module>, z.ZodArray<z.ZodType<Chunk, z.ZodTypeDef, Chunk>, "many">, z.ZodString], z.ZodUnknown>, z.ZodOptional<z.ZodString>>]>>;
filename: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodType<PathData, z.ZodTypeDef, PathData>, z.ZodOptional<z.ZodType<JsAssetInfo, z.ZodTypeDef, JsAssetInfo>>], z.ZodUnknown>, z.ZodString>]>>;
minSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
maxSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
maxAsyncSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
Expand All @@ -7160,6 +7160,7 @@ export const rspackOptions: z.ZodObject<{
minChunks: z.ZodOptional<z.ZodNumber>;
usedExports: z.ZodOptional<z.ZodBoolean>;
name: z.ZodOptional<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodLiteral<false>]>, z.ZodFunction<z.ZodTuple<[z.ZodType<Module, z.ZodTypeDef, Module>, z.ZodArray<z.ZodType<Chunk, z.ZodTypeDef, Chunk>, "many">, z.ZodString], z.ZodUnknown>, z.ZodOptional<z.ZodString>>]>>;
filename: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodType<PathData, z.ZodTypeDef, PathData>, z.ZodOptional<z.ZodType<JsAssetInfo, z.ZodTypeDef, JsAssetInfo>>], z.ZodUnknown>, z.ZodString>]>>;
minSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
maxSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
maxAsyncSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>;
Expand All @@ -7170,7 +7171,6 @@ export const rspackOptions: z.ZodObject<{
test: z.ZodOptional<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, z.ZodFunction<z.ZodTuple<[z.ZodType<Module, z.ZodTypeDef, Module>], z.ZodUnknown>, z.ZodUnknown>]>>;
priority: z.ZodOptional<z.ZodNumber>;
enforce: z.ZodOptional<z.ZodBoolean>;
filename: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodType<PathData, z.ZodTypeDef, PathData>, z.ZodOptional<z.ZodType<JsAssetInfo, z.ZodTypeDef, JsAssetInfo>>], z.ZodUnknown>, z.ZodString>]>>;
reuseExistingChunk: z.ZodOptional<z.ZodBoolean>;
type: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>>;
idHint: z.ZodOptional<z.ZodString>;
Expand Down Expand Up @@ -7244,6 +7244,7 @@ export const rspackOptions: z.ZodObject<{
}, "strict", z.ZodTypeAny, {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -7288,6 +7289,7 @@ export const rspackOptions: z.ZodObject<{
}, {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -7371,6 +7373,7 @@ export const rspackOptions: z.ZodObject<{
splitChunks?: false | {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -7439,6 +7442,7 @@ export const rspackOptions: z.ZodObject<{
splitChunks?: false | {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -9067,6 +9071,7 @@ export const rspackOptions: z.ZodObject<{
splitChunks?: false | {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -9674,6 +9679,7 @@ export const rspackOptions: z.ZodObject<{
splitChunks?: false | {
chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined;
name?: string | false | ((args_0: Module, args_1: Chunk[], args_2: string, ...args: unknown[]) => string | undefined) | undefined;
filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined;
usedExports?: boolean | undefined;
defaultSizeTypes?: string[] | undefined;
cacheGroups?: Record<string, false | {
Expand Down Expand Up @@ -10149,6 +10155,7 @@ type SharedOptimizationSplitChunksCacheGroup = {
minChunks?: number;
usedExports?: boolean;
name?: false | OptimizationSplitChunksName;
filename?: Filename;
minSize?: OptimizationSplitChunksSizes;
maxSize?: OptimizationSplitChunksSizes;
maxAsyncSize?: OptimizationSplitChunksSizes;
Expand Down
6 changes: 3 additions & 3 deletions packages/rspack/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,9 @@ type SharedOptimizationSplitChunksCacheGroup = {
* */
name?: false | OptimizationSplitChunksName;

/** Allows to override the filename when and only when it's an initial chunk. */
filename?: Filename;

/**
* Minimum size, in bytes, for a chunk to be generated.
*
Expand Down Expand Up @@ -2202,9 +2205,6 @@ export type OptimizationSplitChunksCacheGroup = {
*/
enforce?: boolean;

/** Allows to override the filename when and only when it's an initial chunk. */
filename?: Filename;

/**
* Whether to reuse existing chunks when possible.
* @default false
Expand Down
2 changes: 1 addition & 1 deletion packages/rspack/src/config/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,7 @@ const sharedOptimizationSplitChunksCacheGroup = {
minChunks: z.number().min(1).optional(),
usedExports: z.boolean().optional(),
name: optimizationSplitChunksName.optional(),
filename: filename.optional(),
minSize: optimizationSplitChunksSizes.optional(),
maxSize: optimizationSplitChunksSizes.optional(),
maxAsyncSize: optimizationSplitChunksSizes.optional(),
Expand All @@ -1226,7 +1227,6 @@ const optimizationSplitChunksCacheGroup = z.strictObject({
.optional(),
priority: z.number().optional(),
enforce: z.boolean().optional(),
filename: filename.optional(),
reuseExistingChunk: z.boolean().optional(),
type: z.string().or(z.instanceof(RegExp)).optional(),
idHint: z.string().optional(),
Expand Down
52 changes: 27 additions & 25 deletions website/docs/en/plugins/webpack/split-chunks-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,33 @@ If the `splitChunks.name` matches an [entry point](/config/entry) name, the entr

:::

### splitChunks.filename

#### splitChunks.cacheGroups.\{cacheGroup\}.filename

- **Type:** `string | function`

Allows to override the filename when and only when it's an initial chunk. All placeholders available in output.filename are also available here.

```js title="rspack.config.mjs"
export default {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'vendors-[name].js',
// or
filename: (pathData, assetInfo) => {
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};
```

### splitChunks.usedExports

<ApiMeta addedVersion="1.0.0" />
Expand Down Expand Up @@ -323,31 +350,6 @@ Tells Rspack to ignore `splitChunks.minSize`, splitChunks`.minChunks`, `splitChu

Sets the hint for chunk id. It will be added to chunk's filename.

#### splitChunks.cacheGroups.\{cacheGroup\}.filename

- **Type:** `string | function`

Allows to override the filename when and only when it's an initial chunk. All placeholders available in output.filename are also available here.

```js title="rspack.config.mjs"
export default {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'vendors-[name].js',
// or
filename: (pathData, assetInfo) => {
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};
```

#### splitChunks.cacheGroups.\{cacheGroup\}.reuseExistingChunk

- **Type:** `boolean`
Expand Down
52 changes: 27 additions & 25 deletions website/docs/zh/plugins/webpack/split-chunks-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,33 @@ export default {

:::

### splitChunks.filename

#### splitChunks.cacheGroups.\{cacheGroup\}.filename

- **类型:** `string | function`

仅在初始 chunk 时才允许覆盖文件名。 也可以在 output.filename 中使用所有占位符。

```js title="rspack.config.mjs"
export default {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'vendors-[name].js',
// or
filename: (pathData, assetInfo) => {
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};
```

### splitChunks.usedExports

<ApiMeta addedVersion="1.0.0" />
Expand Down Expand Up @@ -313,31 +340,6 @@ export default {

设置 chunk id 的提示。 它将被添加到 chunk 的文件名中。

#### splitChunks.cacheGroups.\{cacheGroup\}.filename

- **类型:** `string | function`

仅在初始 chunk 时才允许覆盖文件名。 也可以在 output.filename 中使用所有占位符。

```js title="rspack.config.mjs"
export default {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'vendors-[name].js',
// or
filename: (pathData, assetInfo) => {
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};
```

#### splitChunks.cacheGroups.\{cacheGroup\}.reuseExistingChunk

- **类型:** `boolean`
Expand Down

2 comments on commit d688f4d

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on d688f4d Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2025-02-11 9d82335) Current Change
10000_big_production-mode_disable-minimize + exec 37.7 s ± 637 ms 39.2 s ± 983 ms +3.80 %
10000_development-mode + exec 1.88 s ± 89 ms 1.82 s ± 21 ms -2.79 %
10000_development-mode_hmr + exec 685 ms ± 7.4 ms 687 ms ± 9.4 ms +0.24 %
10000_production-mode + exec 2.28 s ± 51 ms 2.3 s ± 120 ms +0.80 %
10000_production-mode_persistent-cold + exec 2.47 s ± 72 ms 2.48 s ± 98 ms +0.57 %
10000_production-mode_persistent-hot + exec 1.65 s ± 61 ms 1.66 s ± 49 ms +0.40 %
arco-pro_development-mode + exec 1.78 s ± 145 ms 1.74 s ± 123 ms -2.31 %
arco-pro_development-mode_hmr + exec 389 ms ± 2.1 ms 388 ms ± 2.6 ms -0.26 %
arco-pro_production-mode + exec 3.59 s ± 217 ms 3.69 s ± 122 ms +2.70 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.72 s ± 229 ms 3.69 s ± 173 ms -0.84 %
arco-pro_production-mode_persistent-cold + exec 3.85 s ± 164 ms 3.86 s ± 61 ms +0.24 %
arco-pro_production-mode_persistent-hot + exec 2.36 s ± 99 ms 2.47 s ± 290 ms +4.77 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.63 s ± 69 ms 3.79 s ± 158 ms +4.47 %
large-dyn-imports_development-mode + exec 2.09 s ± 24 ms 2.11 s ± 103 ms +0.73 %
large-dyn-imports_production-mode + exec 2.15 s ± 71 ms 2.15 s ± 14 ms -0.18 %
threejs_development-mode_10x + exec 1.54 s ± 25 ms 1.54 s ± 14 ms +0.20 %
threejs_development-mode_10x_hmr + exec 779 ms ± 7 ms 790 ms ± 6.6 ms +1.44 %
threejs_production-mode_10x + exec 5.2 s ± 32 ms 5.27 s ± 145 ms +1.36 %
threejs_production-mode_10x_persistent-cold + exec 5.27 s ± 65 ms 5.37 s ± 311 ms +1.74 %
threejs_production-mode_10x_persistent-hot + exec 4.53 s ± 220 ms 4.55 s ± 190 ms +0.39 %
10000_big_production-mode_disable-minimize + rss memory 8706 MiB ± 32.4 MiB 8753 MiB ± 253 MiB +0.54 %
10000_development-mode + rss memory 649 MiB ± 12.6 MiB 665 MiB ± 14.4 MiB +2.57 %
10000_development-mode_hmr + rss memory 1344 MiB ± 112 MiB 1304 MiB ± 164 MiB -3.02 %
10000_production-mode + rss memory 621 MiB ± 21.8 MiB 644 MiB ± 18.6 MiB +3.77 %
10000_production-mode_persistent-cold + rss memory 746 MiB ± 24.7 MiB 756 MiB ± 6.2 MiB +1.22 %
10000_production-mode_persistent-hot + rss memory 717 MiB ± 23.3 MiB 744 MiB ± 22.8 MiB +3.83 %
arco-pro_development-mode + rss memory 569 MiB ± 17.5 MiB 589 MiB ± 22.9 MiB +3.45 %
arco-pro_development-mode_hmr + rss memory 643 MiB ± 49.1 MiB 686 MiB ± 56.3 MiB +6.74 %
arco-pro_production-mode + rss memory 714 MiB ± 28.8 MiB 728 MiB ± 23.1 MiB +1.94 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 732 MiB ± 22.4 MiB 752 MiB ± 26 MiB +2.65 %
arco-pro_production-mode_persistent-cold + rss memory 853 MiB ± 45.5 MiB 851 MiB ± 34.4 MiB -0.23 %
arco-pro_production-mode_persistent-hot + rss memory 708 MiB ± 27.8 MiB 750 MiB ± 12.4 MiB +5.90 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 727 MiB ± 48.2 MiB 724 MiB ± 24.1 MiB -0.40 %
large-dyn-imports_development-mode + rss memory 644 MiB ± 5.26 MiB 659 MiB ± 3 MiB +2.36 %
large-dyn-imports_production-mode + rss memory 526 MiB ± 7.84 MiB 548 MiB ± 7.5 MiB +4.15 %
threejs_development-mode_10x + rss memory 553 MiB ± 16.3 MiB 551 MiB ± 11.4 MiB -0.35 %
threejs_development-mode_10x_hmr + rss memory 1145 MiB ± 140 MiB 1122 MiB ± 140 MiB -1.98 %
threejs_production-mode_10x + rss memory 828 MiB ± 50.8 MiB 838 MiB ± 40.5 MiB +1.24 %
threejs_production-mode_10x_persistent-cold + rss memory 960 MiB ± 14.5 MiB 937 MiB ± 53.6 MiB -2.39 %
threejs_production-mode_10x_persistent-hot + rss memory 877 MiB ± 54.8 MiB 893 MiB ± 44.6 MiB +1.77 %

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on d688f4d Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ecosystem CI detail: Open

suite result
modernjs ❌ failure
rspress ✅ success
rslib ❌ failure
rsbuild ❌ failure
rsdoctor ❌ failure
examples ✅ success
devserver ✅ success
nuxt ✅ success

Please sign in to comment.