diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 6aadbe376b0..6605f1a21aa 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -1176,7 +1176,7 @@ export interface RawCacheGroupOptions { key: string priority?: number test?: RegExp | string | Function - filename?: string + filename?: JsFilename idHint?: string /** What kind of chunks should be selected. */ chunks?: RegExp | 'async' | 'initial' | 'all' diff --git a/crates/rspack_binding_values/src/raw_options/raw_split_chunks/mod.rs b/crates/rspack_binding_values/src/raw_options/raw_split_chunks/mod.rs index 4140516f075..6740b3fa4d5 100644 --- a/crates/rspack_binding_values/src/raw_options/raw_split_chunks/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/raw_split_chunks/mod.rs @@ -23,6 +23,7 @@ use self::raw_split_chunk_cache_group_test::RawCacheGroupTest; use self::raw_split_chunk_chunks::{create_chunks_filter, Chunks}; use self::raw_split_chunk_name::default_chunk_option_name; use self::raw_split_chunk_size::RawSplitChunkSizes; +use crate::JsFilename; #[napi(object, object_to_js = false)] #[derive(Debug)] @@ -63,7 +64,7 @@ pub struct RawCacheGroupOptions { #[napi(ts_type = "RegExp | string | Function")] #[debug(skip)] pub test: Option, - pub filename: Option, + pub filename: Option, // pub enforce: bool, pub id_hint: Option, /// What kind of chunks should be selected. diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/a.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/a.js new file mode 100644 index 00000000000..e79a0617010 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/a.js @@ -0,0 +1,24 @@ +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", () => { + const files = require("fs").readdirSync(__dirname); + expect(files).toContain("a.js"); + expect(files).toContain("b.js"); + expect(files).toContain("common-common1_js.js"); + expect(files).toContain("common-common2_js.js"); + expect(files).toContain("common-common3_js.js"); + expect(files).toContain("shared-shared-shared1_js.js"); + expect(files).toContain("shared-shared-shared2_js.js"); +}); diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/b.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/b.js new file mode 100644 index 00000000000..f7422f1f99e --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/b.js @@ -0,0 +1,5 @@ +import "./shared1"; +import "./shared2"; +import "./common1"; +import "./common2"; +import "./common3"; diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common1.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common1.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common2.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common2.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common3.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/common3.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/rspack.config.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/rspack.config.js new file mode 100644 index 00000000000..3dbab2563af --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/rspack.config.js @@ -0,0 +1,34 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + mode: "development", + entry: { + a: "./a", + b: "./b" + }, + output: { + filename: "[name].js", + libraryTarget: "commonjs2" + }, + optimization: { + chunkIds: "named", + splitChunks: { + cacheGroups: { + shared: { + chunks: "all", + test: /shared/, + filename: (pathData, assetInfo) => { + expect(pathData).toBeDefined() + expect(typeof assetInfo).toBe('object') + return "shared-[name].js" + }, + enforce: true + }, + common: { + chunks: "all", + test: /common/, + enforce: true + } + } + } + } +}; diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/shared1.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/shared1.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/shared2.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/shared2.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/test.config.js b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/test.config.js new file mode 100644 index 00000000000..a8c9e9360a0 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/split-chunks/custom-filename-function/test.config.js @@ -0,0 +1,6 @@ +/** @type {import("../../../..").TConfigCaseConfig} */ +module.exports = { + findBundle: function (i, options) { + return ["a.js"]; + } +}; diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 785a9a494e6..bc170297f70 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -4128,7 +4128,7 @@ export type OptimizationSplitChunksCacheGroup = { test?: string | RegExp | ((module: Module) => unknown); priority?: number; enforce?: boolean; - filename?: string; + filename?: Filename; reuseExistingChunk?: boolean; type?: string | RegExp; idHint?: string; @@ -6968,13 +6968,13 @@ export const rspackOptions: z.ZodObject<{ test: z.ZodOptional]>, z.ZodFunction], z.ZodUnknown>, z.ZodUnknown>]>>; priority: z.ZodOptional; enforce: z.ZodOptional; - filename: z.ZodOptional; + filename: z.ZodOptional, z.ZodOptional>], z.ZodUnknown>, z.ZodString>]>>; reuseExistingChunk: z.ZodOptional; type: z.ZodOptional]>>; idHint: z.ZodOptional; }, "strict", z.ZodTypeAny, { name?: string | false | ((args_0: Module | undefined, ...args: unknown[]) => unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -6994,7 +6994,7 @@ export const rspackOptions: z.ZodObject<{ idHint?: string | undefined; }, { name?: string | false | ((args_0: Module | undefined, ...args: unknown[]) => unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -7043,7 +7043,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -7086,7 +7086,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -7166,7 +7166,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -7232,7 +7232,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -8855,7 +8855,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; @@ -9457,7 +9457,7 @@ export const rspackOptions: z.ZodObject<{ defaultSizeTypes?: string[] | undefined; cacheGroups?: Record unknown) | undefined; - filename?: string | undefined; + filename?: string | ((args_0: PathData, args_1: JsAssetInfo | undefined, ...args: unknown[]) => string) | undefined; type?: string | RegExp | undefined; chunks?: RegExp | "initial" | "async" | "all" | ((args_0: Chunk, ...args: unknown[]) => boolean) | undefined; usedExports?: boolean | undefined; diff --git a/packages/rspack/src/config/types.ts b/packages/rspack/src/config/types.ts index 879843399e4..7dcaf48c925 100644 --- a/packages/rspack/src/config/types.ts +++ b/packages/rspack/src/config/types.ts @@ -2165,7 +2165,7 @@ export type OptimizationSplitChunksCacheGroup = { enforce?: boolean; /** Allows to override the filename when and only when it's an initial chunk. */ - filename?: string; + filename?: Filename; /** * Whether to reuse existing chunks when possible. diff --git a/packages/rspack/src/config/zod.ts b/packages/rspack/src/config/zod.ts index 1efac5c3f03..9099f8ae6e7 100644 --- a/packages/rspack/src/config/zod.ts +++ b/packages/rspack/src/config/zod.ts @@ -1218,7 +1218,7 @@ const optimizationSplitChunksCacheGroup = z.strictObject({ .optional(), priority: z.number().optional(), enforce: z.boolean().optional(), - filename: z.string().optional(), + filename: filename.optional(), reuseExistingChunk: z.boolean().optional(), type: z.string().or(z.instanceof(RegExp)).optional(), idHint: z.string().optional(), diff --git a/website/docs/en/plugins/webpack/split-chunks-plugin.mdx b/website/docs/en/plugins/webpack/split-chunks-plugin.mdx index acdf30125f1..238997423f2 100644 --- a/website/docs/en/plugins/webpack/split-chunks-plugin.mdx +++ b/website/docs/en/plugins/webpack/split-chunks-plugin.mdx @@ -325,7 +325,7 @@ Sets the hint for chunk id. It will be added to chunk's filename. #### splitChunks.cacheGroups.\{cacheGroup\}.filename -- **Type:** `string` +- **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. @@ -337,6 +337,10 @@ module.exports = { cacheGroups: { defaultVendors: { filename: 'vendors-[name].js', + // or + filename: (pathData, assetInfo) => { + return `${pathData.chunk.name}-bundle.js`; + }, }, }, }, diff --git a/website/docs/zh/plugins/webpack/split-chunks-plugin.mdx b/website/docs/zh/plugins/webpack/split-chunks-plugin.mdx index 88da4d41502..4c5e37d352e 100644 --- a/website/docs/zh/plugins/webpack/split-chunks-plugin.mdx +++ b/website/docs/zh/plugins/webpack/split-chunks-plugin.mdx @@ -315,7 +315,7 @@ module.exports = { #### splitChunks.cacheGroups.\{cacheGroup\}.filename -- **类型:** `string` +- **类型:** `string | function` 仅在初始 chunk 时才允许覆盖文件名。 也可以在 output.filename 中使用所有占位符。 @@ -327,6 +327,10 @@ module.exports = { cacheGroups: { defaultVendors: { filename: 'vendors-[name].js', + // or + filename: (pathData, assetInfo) => { + return `${pathData.chunk.name}-bundle.js`; + }, }, }, },