diff --git a/e2e/cases/output/copy/index.test.ts b/e2e/cases/output/copy/index.test.ts index cfbd8801e4..c03de4183c 100644 --- a/e2e/cases/output/copy/index.test.ts +++ b/e2e/cases/output/copy/index.test.ts @@ -2,6 +2,7 @@ import fs from 'node:fs'; import { join } from 'node:path'; import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; +import type { RsbuildPlugin } from '@rsbuild/core'; test('should copy asset to dist folder correctly', async () => { await build({ @@ -49,3 +50,56 @@ test('should copy asset to dist sub-folder correctly', async () => { expect(fs.existsSync(join(__dirname, 'dist-1/foo/icon.png'))).toBeTruthy(); }); + +test('should merge copy config correctly', async () => { + const rsbuildPlugin = (): RsbuildPlugin => ({ + name: 'example', + setup(api) { + api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => { + return mergeRsbuildConfig(config, { + output: { + copy: { + patterns: [ + { + from: '../../../assets/icon.png', + }, + ], + }, + }, + }); + }); + }, + }); + + const rsbuildPlugin2 = (): RsbuildPlugin => ({ + name: 'example2', + setup(api) { + api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => { + return mergeRsbuildConfig(config, { + output: { + copy: [ + { + from: '../../../assets/image.png', + }, + ], + }, + }); + }); + }, + }); + + await build({ + cwd: __dirname, + rsbuildConfig: { + output: { + distPath: { + root: 'dist-4', + }, + }, + plugins: [rsbuildPlugin(), rsbuildPlugin2()], + }, + }); + + expect(fs.existsSync(join(__dirname, 'dist-4/icon.png'))).toBeTruthy(); + expect(fs.existsSync(join(__dirname, 'dist-4/image.png'))).toBeTruthy(); +}); diff --git a/packages/core/src/mergeConfig.ts b/packages/core/src/mergeConfig.ts index 8c2e602def..b199a8cbb7 100644 --- a/packages/core/src/mergeConfig.ts +++ b/packages/core/src/mergeConfig.ts @@ -25,7 +25,7 @@ const isOverridePath = (key: string) => { return OVERRIDE_PATHS.includes(key); }; -const merge = (x: unknown, y: unknown, path = '') => { +const merge = (x: unknown, y: unknown, path = ''): unknown => { // force some keys to override if (isOverridePath(path)) { return y ?? x; @@ -48,6 +48,12 @@ const merge = (x: unknown, y: unknown, path = '') => { // combine array if (pair.some(Array.isArray)) { + if (path === 'output.copy' && !pair.every(Array.isArray)) { + // x: { patterns: [A] }、y: [B, C] => { patterns: [A,B,C] } + return Array.isArray(x) + ? merge({ patterns: x }, y, path) + : merge(x, { patterns: y }, path); + } return [...castArray(x), ...castArray(y)]; }