From 0f25563318ab85445ec902b8cceee984824dada8 Mon Sep 17 00:00:00 2001 From: neverland Date: Mon, 13 Oct 2025 16:55:29 +0800 Subject: [PATCH] feat: support shorter string value for `output.distPath` --- .../custom-dist-path-string/index.test.ts | 12 ++++ .../custom-dist-path-string/rsbuild.config.ts | 8 +++ .../custom-dist-path-string/src/index.js | 1 + .../assets/emit-assets/rsbuild.config.ts | 6 +- .../cli/config-loader/rsbuild.config.auto.mts | 4 +- .../cli/config-loader/rsbuild.config.mts | 4 +- e2e/cases/cli/custom-config/custom.config.mjs | 4 +- .../cli/function-config/rsbuild.config.ts | 4 +- .../load-import-meta-env/rsbuild.config.ts | 4 +- e2e/cases/cli/load-node-env/rsbuild.config.ts | 4 +- .../cli/load-process-env/rsbuild.config.ts | 4 +- e2e/cases/cli/node-env/rsbuild.config.mjs | 4 +- e2e/cases/cli/reload-config/index.test.ts | 9 +-- .../specified-environment/rsbuild.config.mjs | 8 +-- e2e/cases/config/debug-mode/index.test.ts | 8 +-- e2e/cases/config/inspect-config/index.test.ts | 6 +- e2e/cases/environments/basic/index.test.ts | 12 +--- .../build-custom-dist/rsbuild.config.ts | 4 +- .../environments/plugins/rsbuild.config.ts | 4 +- .../rsbuild.config.ts | 8 +-- .../output/clean-dist-path/index.test.ts | 4 +- e2e/cases/output/copy/index.test.ts | 12 +--- e2e/cases/output/manifest/index.test.ts | 8 +-- .../plugin-after-build-hook/index.test.ts | 6 +- .../rsbuild.config.ts | 5 +- .../rsbuild.config.ts | 10 +--- .../rsbuild.config.ts | 10 +--- e2e/cases/print-file-size/basic/index.test.ts | 14 +---- e2e/cases/profiling/rspack-profile/dev.mjs | 4 +- .../resolve/alias-by-target/rsbuild.config.ts | 7 +-- .../resolve/alias-legecy/rsbuild.config.ts | 7 +-- e2e/cases/security/nonce-basic/index.test.ts | 9 +-- e2e/cases/server/multi-server/index.test.ts | 8 +-- e2e/cases/server/print-urls/index.test.ts | 10 +--- e2e/cases/server/prod-server/index.test.ts | 36 +++--------- e2e/cases/server/public-dir/publicDir.test.ts | 56 +++++-------------- .../server/ssr-type-module/rsbuild.config.ts | 3 - e2e/cases/server/ssr/rsbuild.config.ts | 3 - .../write-to-disk-environments/index.test.ts | 21 ++----- e2e/cases/server/write-to-disk/index.test.ts | 12 +--- .../source/multiple-entry/rsbuild.config.ts | 7 +-- packages/core/src/createContext.ts | 6 +- packages/core/src/defaultConfig.ts | 42 +++++++++++--- packages/core/src/provider/initConfigs.ts | 17 ++++-- packages/core/src/types/config.ts | 4 +- website/docs/en/config/output/dist-path.mdx | 42 +++++++++----- website/docs/zh/config/output/dist-path.mdx | 42 +++++++++----- 47 files changed, 201 insertions(+), 322 deletions(-) create mode 100644 e2e/cases/assets/custom-dist-path-string/index.test.ts create mode 100644 e2e/cases/assets/custom-dist-path-string/rsbuild.config.ts create mode 100644 e2e/cases/assets/custom-dist-path-string/src/index.js diff --git a/e2e/cases/assets/custom-dist-path-string/index.test.ts b/e2e/cases/assets/custom-dist-path-string/index.test.ts new file mode 100644 index 0000000000..1f820ccda8 --- /dev/null +++ b/e2e/cases/assets/custom-dist-path-string/index.test.ts @@ -0,0 +1,12 @@ +import { expect, test } from '@e2e/helper'; + +test('should set `output.distPath` to a string', async ({ build }) => { + const rsbuild = await build(); + const files = rsbuild.getDistFiles(); + const filenames = Object.keys(files); + expect( + filenames.some((filename) => + filename.includes('dist-custom/static/js/index.js'), + ), + ).toBeTruthy(); +}); diff --git a/e2e/cases/assets/custom-dist-path-string/rsbuild.config.ts b/e2e/cases/assets/custom-dist-path-string/rsbuild.config.ts new file mode 100644 index 0000000000..ca2c5bef05 --- /dev/null +++ b/e2e/cases/assets/custom-dist-path-string/rsbuild.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from '@rsbuild/core'; + +export default defineConfig({ + output: { + filenameHash: false, + distPath: 'dist-custom', + }, +}); diff --git a/e2e/cases/assets/custom-dist-path-string/src/index.js b/e2e/cases/assets/custom-dist-path-string/src/index.js new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/e2e/cases/assets/custom-dist-path-string/src/index.js @@ -0,0 +1 @@ +// empty diff --git a/e2e/cases/assets/emit-assets/rsbuild.config.ts b/e2e/cases/assets/emit-assets/rsbuild.config.ts index 114f9f61df..c2b71a0061 100644 --- a/e2e/cases/assets/emit-assets/rsbuild.config.ts +++ b/e2e/cases/assets/emit-assets/rsbuild.config.ts @@ -5,11 +5,7 @@ export default defineConfig({ filenameHash: false, }, environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', diff --git a/e2e/cases/cli/config-loader/rsbuild.config.auto.mts b/e2e/cases/cli/config-loader/rsbuild.config.auto.mts index 616cbe286e..4e82d0a8dd 100644 --- a/e2e/cases/cli/config-loader/rsbuild.config.auto.mts +++ b/e2e/cases/cli/config-loader/rsbuild.config.auto.mts @@ -3,8 +3,6 @@ import distPathJson from './path.json'; export default { output: { - distPath: { - root: distPathJson.distPath, - }, + distPath: distPathJson.distPath, }, } satisfies RsbuildConfig; diff --git a/e2e/cases/cli/config-loader/rsbuild.config.mts b/e2e/cases/cli/config-loader/rsbuild.config.mts index cae7335a55..df39787f57 100644 --- a/e2e/cases/cli/config-loader/rsbuild.config.mts +++ b/e2e/cases/cli/config-loader/rsbuild.config.mts @@ -2,8 +2,6 @@ import type { RsbuildConfig } from '@rsbuild/core'; export default { output: { - distPath: { - root: 'dist-custom', - }, + distPath: 'dist-custom', }, } satisfies RsbuildConfig; diff --git a/e2e/cases/cli/custom-config/custom.config.mjs b/e2e/cases/cli/custom-config/custom.config.mjs index e57b2c3fdc..dd375556e6 100644 --- a/e2e/cases/cli/custom-config/custom.config.mjs +++ b/e2e/cases/cli/custom-config/custom.config.mjs @@ -2,8 +2,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { - distPath: { - root: 'dist-custom', - }, + distPath: 'dist-custom', }, }); diff --git a/e2e/cases/cli/function-config/rsbuild.config.ts b/e2e/cases/cli/function-config/rsbuild.config.ts index 6541bc131b..1b1c91c1f1 100644 --- a/e2e/cases/cli/function-config/rsbuild.config.ts +++ b/e2e/cases/cli/function-config/rsbuild.config.ts @@ -2,8 +2,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig(({ env, command }) => ({ output: { - distPath: { - root: `dist-${env}-${command}`, - }, + distPath: `dist-${env}-${command}`, }, })); diff --git a/e2e/cases/cli/load-import-meta-env/rsbuild.config.ts b/e2e/cases/cli/load-import-meta-env/rsbuild.config.ts index 85c8f5836a..c0ac729070 100644 --- a/e2e/cases/cli/load-import-meta-env/rsbuild.config.ts +++ b/e2e/cases/cli/load-import-meta-env/rsbuild.config.ts @@ -3,8 +3,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { - distPath: { - root: `dist/${import.meta.env.FOO}`, - }, + distPath: `dist/${import.meta.env.FOO}`, }, }); diff --git a/e2e/cases/cli/load-node-env/rsbuild.config.ts b/e2e/cases/cli/load-node-env/rsbuild.config.ts index 3daa3b581b..b4f5a0c953 100644 --- a/e2e/cases/cli/load-node-env/rsbuild.config.ts +++ b/e2e/cases/cli/load-node-env/rsbuild.config.ts @@ -2,8 +2,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { - distPath: { - root: `dist/${process.env.NODE_ENV}`, - }, + distPath: `dist/${process.env.NODE_ENV}`, }, }); diff --git a/e2e/cases/cli/load-process-env/rsbuild.config.ts b/e2e/cases/cli/load-process-env/rsbuild.config.ts index ec069c3317..6a2aca1d86 100644 --- a/e2e/cases/cli/load-process-env/rsbuild.config.ts +++ b/e2e/cases/cli/load-process-env/rsbuild.config.ts @@ -2,8 +2,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { - distPath: { - root: `dist/${process.env.FOO}`, - }, + distPath: `dist/${process.env.FOO}`, }, }); diff --git a/e2e/cases/cli/node-env/rsbuild.config.mjs b/e2e/cases/cli/node-env/rsbuild.config.mjs index e03f5b26da..3ac8468857 100644 --- a/e2e/cases/cli/node-env/rsbuild.config.mjs +++ b/e2e/cases/cli/node-env/rsbuild.config.mjs @@ -2,8 +2,6 @@ import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { - distPath: { - root: process.env.NODE_ENV === 'production' ? 'dist-prod' : 'dist-dev', - }, + distPath: process.env.NODE_ENV === 'production' ? 'dist-prod' : 'dist-dev', }, }); diff --git a/e2e/cases/cli/reload-config/index.test.ts b/e2e/cases/cli/reload-config/index.test.ts index bdce4444f3..7bfe604865 100644 --- a/e2e/cases/cli/reload-config/index.test.ts +++ b/e2e/cases/cli/reload-config/index.test.ts @@ -20,11 +20,6 @@ rspackTest( dev: { writeToDisk: true, }, - output: { - distPath: { - root: 'dist', - }, - }, server: { port: ${await getRandomPort()} } };`, ); @@ -40,9 +35,7 @@ rspackTest( writeToDisk: true, }, output: { - distPath: { - root: 'dist-2', - }, + distPath: 'dist-2', }, server: { port: ${await getRandomPort()} } };`, diff --git a/e2e/cases/cli/specified-environment/rsbuild.config.mjs b/e2e/cases/cli/specified-environment/rsbuild.config.mjs index 8cb3a3eda0..c894a6b0ed 100644 --- a/e2e/cases/cli/specified-environment/rsbuild.config.mjs +++ b/e2e/cases/cli/specified-environment/rsbuild.config.mjs @@ -4,16 +4,12 @@ export default defineConfig({ environments: { web1: { output: { - distPath: { - root: 'dist/web1', - }, + distPath: 'dist/web1', }, }, web2: { output: { - distPath: { - root: 'dist/web2', - }, + distPath: 'dist/web2', }, }, }, diff --git a/e2e/cases/config/debug-mode/index.test.ts b/e2e/cases/config/debug-mode/index.test.ts index 9fc10ab628..7ddee9cf99 100644 --- a/e2e/cases/config/debug-mode/index.test.ts +++ b/e2e/cases/config/debug-mode/index.test.ts @@ -23,9 +23,7 @@ test('should generate config files in debug mode when build', async ({ const rsbuild = await build({ config: { output: { - distPath: { - root: distRoot, - }, + distPath: distRoot, }, }, }); @@ -52,9 +50,7 @@ test('should generate config files in debug mode when dev', async ({ const rsbuild = await dev({ config: { output: { - distPath: { - root: distRoot, - }, + distPath: distRoot, }, }, page, diff --git a/e2e/cases/config/inspect-config/index.test.ts b/e2e/cases/config/inspect-config/index.test.ts index e5d0fc833a..f8ce625028 100644 --- a/e2e/cases/config/inspect-config/index.test.ts +++ b/e2e/cases/config/inspect-config/index.test.ts @@ -96,11 +96,7 @@ rspackTest( cwd: __dirname, config: { environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', diff --git a/e2e/cases/environments/basic/index.test.ts b/e2e/cases/environments/basic/index.test.ts index faaaf84eeb..2ed64886df 100644 --- a/e2e/cases/environments/basic/index.test.ts +++ b/e2e/cases/environments/basic/index.test.ts @@ -7,11 +7,7 @@ test('should build successfully with multiple environments', async ({ await buildPreview({ config: { environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', @@ -32,11 +28,7 @@ test('should serve successfully in dev with multiple environments', async ({ await dev({ config: { environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', diff --git a/e2e/cases/environments/build-custom-dist/rsbuild.config.ts b/e2e/cases/environments/build-custom-dist/rsbuild.config.ts index 2721fe1303..b4a9245cb0 100644 --- a/e2e/cases/environments/build-custom-dist/rsbuild.config.ts +++ b/e2e/cases/environments/build-custom-dist/rsbuild.config.ts @@ -10,9 +10,7 @@ export default defineConfig({ web1: { output: { filenameHash: false, - distPath: { - root: 'dist/web1', - }, + distPath: 'dist/web1', }, }, }, diff --git a/e2e/cases/environments/plugins/rsbuild.config.ts b/e2e/cases/environments/plugins/rsbuild.config.ts index 8400dda45e..eec394e131 100644 --- a/e2e/cases/environments/plugins/rsbuild.config.ts +++ b/e2e/cases/environments/plugins/rsbuild.config.ts @@ -18,9 +18,7 @@ export default defineConfig({ output: { assetPrefix: 'auto', filenameHash: false, - distPath: { - root: 'dist/web1', - }, + distPath: 'dist/web1', }, }, }, diff --git a/e2e/cases/environments/serve-assets-custom-dist/rsbuild.config.ts b/e2e/cases/environments/serve-assets-custom-dist/rsbuild.config.ts index cde710b55a..0403b1e7b0 100644 --- a/e2e/cases/environments/serve-assets-custom-dist/rsbuild.config.ts +++ b/e2e/cases/environments/serve-assets-custom-dist/rsbuild.config.ts @@ -15,9 +15,7 @@ export default defineConfig({ }, }, output: { - distPath: { - root: 'dist/web1', - }, + distPath: 'dist/web1', }, }, web2: { @@ -30,9 +28,7 @@ export default defineConfig({ }, }, output: { - distPath: { - root: 'dist/web2', - }, + distPath: 'dist/web2', }, }, }, diff --git a/e2e/cases/output/clean-dist-path/index.test.ts b/e2e/cases/output/clean-dist-path/index.test.ts index e779aff8f6..afb48f5a02 100644 --- a/e2e/cases/output/clean-dist-path/index.test.ts +++ b/e2e/cases/output/clean-dist-path/index.test.ts @@ -53,9 +53,7 @@ test('should not clean dist path if it is outside root', async ({ build }) => { const rsbuild = await build({ config: { output: { - distPath: { - root: '../node_modules', - }, + distPath: '../node_modules', }, }, }); diff --git a/e2e/cases/output/copy/index.test.ts b/e2e/cases/output/copy/index.test.ts index f54288986a..b275c467af 100644 --- a/e2e/cases/output/copy/index.test.ts +++ b/e2e/cases/output/copy/index.test.ts @@ -8,9 +8,7 @@ test('should copy asset to dist folder correctly', async ({ build }) => { await build({ config: { output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', copy: [{ from: '../../../assets' }], }, }, @@ -39,9 +37,7 @@ test('should copy asset to dist sub-folder correctly', async ({ build }) => { await build({ config: { output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', copy: [{ from: '../../../assets', to: 'foo' }], }, }, @@ -90,9 +86,7 @@ test('should merge copy config correctly', async ({ build }) => { await build({ config: { output: { - distPath: { - root: 'dist-4', - }, + distPath: 'dist-4', }, plugins: [rsbuildPlugin(), rsbuildPlugin2()], }, diff --git a/e2e/cases/output/manifest/index.test.ts b/e2e/cases/output/manifest/index.test.ts index f9e9f0b026..22d6b354c6 100644 --- a/e2e/cases/output/manifest/index.test.ts +++ b/e2e/cases/output/manifest/index.test.ts @@ -65,9 +65,7 @@ test('should generate manifest file when target is node', async ({ build }) => { const rsbuild = await build({ config: { output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', target: 'node', manifest: true, filenameHash: false, @@ -97,9 +95,7 @@ test('should always write manifest to disk when in dev', async ({ dev }) => { const rsbuild = await dev({ config: { output: { - distPath: { - root: 'dist-dev', - }, + distPath: 'dist-dev', manifest: true, filenameHash: false, }, diff --git a/e2e/cases/plugin-api/plugin-after-build-hook/index.test.ts b/e2e/cases/plugin-api/plugin-after-build-hook/index.test.ts index a4b607486c..98b8d8e4bf 100644 --- a/e2e/cases/plugin-api/plugin-after-build-hook/index.test.ts +++ b/e2e/cases/plugin-api/plugin-after-build-hook/index.test.ts @@ -40,11 +40,7 @@ rspackTest( config: { plugins: [plugin], environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', diff --git a/e2e/cases/plugin-api/plugin-process-assets-by-environments/rsbuild.config.ts b/e2e/cases/plugin-api/plugin-process-assets-by-environments/rsbuild.config.ts index 1b6739ff8a..fb32ff0ac4 100644 --- a/e2e/cases/plugin-api/plugin-process-assets-by-environments/rsbuild.config.ts +++ b/e2e/cases/plugin-api/plugin-process-assets-by-environments/rsbuild.config.ts @@ -6,16 +6,13 @@ export default defineConfig({ environments: { web: { output: { - target: 'web', filenameHash: false, }, }, node: { output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/e2e/cases/plugin-api/plugin-transform-by-environments/rsbuild.config.ts b/e2e/cases/plugin-api/plugin-transform-by-environments/rsbuild.config.ts index 421641c807..71e4a8b9b9 100644 --- a/e2e/cases/plugin-api/plugin-transform-by-environments/rsbuild.config.ts +++ b/e2e/cases/plugin-api/plugin-transform-by-environments/rsbuild.config.ts @@ -3,17 +3,11 @@ import { myPlugin } from './myPlugin'; export default { plugins: [myPlugin], environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/e2e/cases/plugin-api/plugin-transform-by-targets/rsbuild.config.ts b/e2e/cases/plugin-api/plugin-transform-by-targets/rsbuild.config.ts index 421641c807..71e4a8b9b9 100644 --- a/e2e/cases/plugin-api/plugin-transform-by-targets/rsbuild.config.ts +++ b/e2e/cases/plugin-api/plugin-transform-by-targets/rsbuild.config.ts @@ -3,17 +3,11 @@ import { myPlugin } from './myPlugin'; export default { plugins: [myPlugin], environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/e2e/cases/print-file-size/basic/index.test.ts b/e2e/cases/print-file-size/basic/index.test.ts index fde90bb10b..7f2ddb161e 100644 --- a/e2e/cases/print-file-size/basic/index.test.ts +++ b/e2e/cases/print-file-size/basic/index.test.ts @@ -59,17 +59,11 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB filenameHash: false, }, environments: { - web: { - output: { - target: 'web', - }, - }, + web: {}, node: { output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, @@ -147,9 +141,7 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB`); const rsbuild = await build({ config: { output: { - distPath: { - root: '../test-temp-folder/dist', - }, + distPath: '../test-temp-folder/dist', }, }, }); diff --git a/e2e/cases/profiling/rspack-profile/dev.mjs b/e2e/cases/profiling/rspack-profile/dev.mjs index 50bad2600f..fa31477851 100644 --- a/e2e/cases/profiling/rspack-profile/dev.mjs +++ b/e2e/cases/profiling/rspack-profile/dev.mjs @@ -15,9 +15,7 @@ async function main() { cliShortcuts: true, }, output: { - distPath: { - root: 'dist-dev', - }, + distPath: 'dist-dev', }, }, }); diff --git a/e2e/cases/resolve/alias-by-target/rsbuild.config.ts b/e2e/cases/resolve/alias-by-target/rsbuild.config.ts index a677684bed..6ee367c330 100644 --- a/e2e/cases/resolve/alias-by-target/rsbuild.config.ts +++ b/e2e/cases/resolve/alias-by-target/rsbuild.config.ts @@ -11,9 +11,6 @@ export default defineConfig({ '@common': './src/common', }, }, - output: { - target: 'web', - }, }, node: { resolve: { @@ -23,9 +20,7 @@ export default defineConfig({ }, output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/e2e/cases/resolve/alias-legecy/rsbuild.config.ts b/e2e/cases/resolve/alias-legecy/rsbuild.config.ts index 3baa6fb0c0..50f6e58ccb 100644 --- a/e2e/cases/resolve/alias-legecy/rsbuild.config.ts +++ b/e2e/cases/resolve/alias-legecy/rsbuild.config.ts @@ -11,9 +11,6 @@ export default defineConfig({ '@common': './src/common', }, }, - output: { - target: 'web', - }, }, node: { source: { @@ -23,9 +20,7 @@ export default defineConfig({ }, output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/e2e/cases/security/nonce-basic/index.test.ts b/e2e/cases/security/nonce-basic/index.test.ts index fbcee52b82..ba9278c945 100644 --- a/e2e/cases/security/nonce-basic/index.test.ts +++ b/e2e/cases/security/nonce-basic/index.test.ts @@ -16,20 +16,13 @@ rspackTest('should apply environment nonce', async ({ build }) => { security: { nonce: 'CSP_NONCE_PLACEHOLDER', }, - output: { - distPath: { - root: 'dist', - }, - }, }, web1: { security: { nonce: 'CSP_NONCE_PLACEHOLDER1', }, output: { - distPath: { - root: 'dist/dist1', - }, + distPath: 'dist/dist1', }, }, }, diff --git a/e2e/cases/server/multi-server/index.test.ts b/e2e/cases/server/multi-server/index.test.ts index fd3dd3ecaa..3f443c7791 100644 --- a/e2e/cases/server/multi-server/index.test.ts +++ b/e2e/cases/server/multi-server/index.test.ts @@ -15,9 +15,7 @@ test.skip('multiple rsbuild dev servers should work correctly', async ({ }, }, output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', }, dev: { assetPrefix: '/app1', @@ -37,9 +35,7 @@ test.skip('multiple rsbuild dev servers should work correctly', async ({ }, }, output: { - distPath: { - root: 'dist-2', - }, + distPath: 'dist-2', }, server: { middlewareMode: true, diff --git a/e2e/cases/server/print-urls/index.test.ts b/e2e/cases/server/print-urls/index.test.ts index e99713bdbd..c3748d1daa 100644 --- a/e2e/cases/server/print-urls/index.test.ts +++ b/e2e/cases/server/print-urls/index.test.ts @@ -206,9 +206,7 @@ test('should print server urls for multiple web environments with custom distPat }, }, output: { - distPath: { - root: '.dist/web1', - }, + distPath: '.dist/web1', }, }, }, @@ -287,15 +285,13 @@ test('should print server urls for web and node environments with custom distPat environments: { web: { output: { - distPath: { - root: 'dist/client', - }, + distPath: 'dist/client', }, }, node: { output: { target: 'node', - distPath: { root: './dist/server' }, + distPath: './dist/server', }, }, }, diff --git a/e2e/cases/server/prod-server/index.test.ts b/e2e/cases/server/prod-server/index.test.ts index ce3746ed9c..5c54a6925f 100644 --- a/e2e/cases/server/prod-server/index.test.ts +++ b/e2e/cases/server/prod-server/index.test.ts @@ -10,9 +10,7 @@ test('should access / and htmlFallback success by default', async ({ const rsbuild = await buildPreview({ config: { output: { - distPath: { - root: 'dist-0', - }, + distPath: 'dist-0', }, }, }); @@ -41,9 +39,7 @@ test('should return 404 when htmlFallback false', async ({ htmlFallback: false, }, output: { - distPath: { - root: 'dist-0', - }, + distPath: 'dist-0', }, }, }); @@ -67,9 +63,7 @@ test('should access /main.html success when entry is main', async ({ }, }, output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', }, }, }); @@ -94,9 +88,7 @@ test('should access /main success when entry is main', async ({ }, }, output: { - distPath: { - root: 'dist-2', - }, + distPath: 'dist-2', }, }, }); @@ -123,9 +115,7 @@ test('should access /main success when entry is main and set assetPrefix', async }, }, output: { - distPath: { - root: 'dist-4', - }, + distPath: 'dist-4', assetPrefix: '/aaaa/', }, }, @@ -151,9 +141,7 @@ test('should access /main success when entry is main and outputPath is /main/ind }, }, output: { - distPath: { - root: 'dist-5', - }, + distPath: 'dist-5', }, html: { outputStructure: 'nested', @@ -181,9 +169,7 @@ test('should return 404 when page is not found', async ({ }, }, output: { - distPath: { - root: 'dist-6', - }, + distPath: 'dist-6', }, }, }); @@ -244,9 +230,7 @@ test('should match resource correctly with specify assetPrefix', async ({ }, output: { assetPrefix: '/subpath/', - distPath: { - root: 'dist-8', - }, + distPath: 'dist-8', }, }, }); @@ -272,9 +256,7 @@ test('should match resource correctly with full url assetPrefix', async ({ }, output: { assetPrefix: `http://localhost:${port}/subpath/`, - distPath: { - root: 'dist-8', - }, + distPath: 'dist-8', }, }, }); diff --git a/e2e/cases/server/public-dir/publicDir.test.ts b/e2e/cases/server/public-dir/publicDir.test.ts index e0ed15ef0c..45c134fa07 100644 --- a/e2e/cases/server/public-dir/publicDir.test.ts +++ b/e2e/cases/server/public-dir/publicDir.test.ts @@ -11,9 +11,7 @@ test('should serve publicDir for dev server correctly', async ({ const rsbuild = await devOnly({ config: { output: { - distPath: { - root: 'dist-dev-1', - }, + distPath: 'dist-dev-1', }, }, }); @@ -38,9 +36,7 @@ test('should serve publicDir with assetPrefix for dev server correctly', async ( }, output: { assetPrefix: '/prod/', - distPath: { - root: 'dist-dev-1', - }, + distPath: 'dist-dev-1', }, }, }); @@ -65,9 +61,7 @@ test('should serve multiple publicDir for dev server correctly', async ({ publicDir: [{ name: 'test-temp-dir1' }, { name: 'test-temp-dir2' }], }, output: { - distPath: { - root: 'dist-dev-1', - }, + distPath: 'dist-dev-1', }, }, }); @@ -96,9 +90,7 @@ test('should serve custom publicDir for dev server correctly', async ({ }, }, output: { - distPath: { - root: 'dist-dev-1', - }, + distPath: 'dist-dev-1', }, }, }); @@ -121,9 +113,7 @@ test('should not serve publicDir when publicDir is false', async ({ htmlFallback: false, }, output: { - distPath: { - root: 'dist-dev-1', - }, + distPath: 'dist-dev-1', }, }, }); @@ -144,9 +134,7 @@ test('should serve publicDir for preview server correctly', async ({ const rsbuild = await buildPreview({ config: { output: { - distPath: { - root: 'dist-build-1', - }, + distPath: 'dist-build-1', }, }, }); @@ -168,24 +156,18 @@ test('should copy publicDir to the environment distDir when multiple environment environments: { web1: { output: { - distPath: { - root: 'dist-build-web-1', - }, + distPath: 'dist-build-web-1', }, }, web2: { output: { - distPath: { - root: 'dist-build-web-2', - }, + distPath: 'dist-build-web-2', }, }, node: { output: { target: 'node', - distPath: { - root: 'dist-build-node', - }, + distPath: 'dist-build-node', }, }, }, @@ -227,9 +209,7 @@ test('should copy publicDir to the node distDir when copyOnBuild is specified as node: { output: { target: 'node', - distPath: { - root: 'dist-build-node-1', - }, + distPath: 'dist-build-node-1', }, }, }, @@ -256,16 +236,12 @@ test('should copy publicDir to root dist when environment dist path has a parent environments: { web1: { output: { - distPath: { - root: 'dist-build-web/1', - }, + distPath: 'dist-build-web/1', }, }, web2: { output: { - distPath: { - root: 'dist-build-web', - }, + distPath: 'dist-build-web', }, }, }, @@ -299,9 +275,7 @@ test('should serve publicDir for preview server with assetPrefix correctly', asy }, output: { assetPrefix: '/prod/', - distPath: { - root: 'dist-build-1', - }, + distPath: 'dist-build-1', }, }, }); @@ -326,9 +300,7 @@ test('should serve multiple publicDir for preview server correctly', async ({ publicDir: [{ name: 'test-temp-dir1' }, { name: 'test-temp-dir2' }], }, output: { - distPath: { - root: 'dist-build-1', - }, + distPath: 'dist-build-1', }, }, }); diff --git a/e2e/cases/server/ssr-type-module/rsbuild.config.ts b/e2e/cases/server/ssr-type-module/rsbuild.config.ts index 44b5003ce8..243184f71f 100644 --- a/e2e/cases/server/ssr-type-module/rsbuild.config.ts +++ b/e2e/cases/server/ssr-type-module/rsbuild.config.ts @@ -45,9 +45,6 @@ export default defineConfig({ }, environments: { web: { - output: { - target: 'web', - }, source: { entry: { index: './src/index', diff --git a/e2e/cases/server/ssr/rsbuild.config.ts b/e2e/cases/server/ssr/rsbuild.config.ts index 3888473caf..0df8b244a8 100644 --- a/e2e/cases/server/ssr/rsbuild.config.ts +++ b/e2e/cases/server/ssr/rsbuild.config.ts @@ -45,9 +45,6 @@ export default defineConfig({ }, environments: { web: { - output: { - target: 'web', - }, source: { entry: { index: './src/index', diff --git a/e2e/cases/server/write-to-disk-environments/index.test.ts b/e2e/cases/server/write-to-disk-environments/index.test.ts index 137ce16dde..5ab6682bcf 100644 --- a/e2e/cases/server/write-to-disk-environments/index.test.ts +++ b/e2e/cases/server/write-to-disk-environments/index.test.ts @@ -24,20 +24,13 @@ test('should handle writeToDisk correctly across multiple environments', async ( }, environments: { web: { - output: { - distPath: { - root: 'dist', - }, - }, dev: { writeToDisk: false, }, }, web1: { output: { - distPath: { - root: 'dist-1', - }, + distPath: 'dist-1', }, dev: { writeToDisk: true, @@ -45,9 +38,7 @@ test('should handle writeToDisk correctly across multiple environments', async ( }, web2: { output: { - distPath: { - root: 'dist-2', - }, + distPath: 'dist-2', }, }, }, @@ -74,9 +65,7 @@ test('should writeToDisk correctly when environment writeToDisk configuration sa environments: { web: { output: { - distPath: { - root: 'dist-same', - }, + distPath: 'dist-same', }, dev: { writeToDisk: true, @@ -84,9 +73,7 @@ test('should writeToDisk correctly when environment writeToDisk configuration sa }, web1: { output: { - distPath: { - root: 'dist-same-1', - }, + distPath: 'dist-same-1', }, dev: { writeToDisk: true, diff --git a/e2e/cases/server/write-to-disk/index.test.ts b/e2e/cases/server/write-to-disk/index.test.ts index 1044a13ff0..02b4720ea1 100644 --- a/e2e/cases/server/write-to-disk/index.test.ts +++ b/e2e/cases/server/write-to-disk/index.test.ts @@ -7,9 +7,7 @@ test('should work with the default writeToDisk configuration', async ({ await dev({ config: { output: { - distPath: { - root: 'dist-write-to-disk-default', - }, + distPath: 'dist-write-to-disk-default', }, }, }); @@ -22,9 +20,7 @@ test('should work when writeToDisk is set to false', async ({ page, dev }) => { await dev({ config: { output: { - distPath: { - root: 'dist-write-to-disk-false', - }, + distPath: 'dist-write-to-disk-false', }, dev: { writeToDisk: false, @@ -40,9 +36,7 @@ test('should work when writeToDisk is set to true', async ({ page, dev }) => { await dev({ config: { output: { - distPath: { - root: 'dist-write-to-disk', - }, + distPath: 'dist-write-to-disk', }, dev: { writeToDisk: true, diff --git a/e2e/cases/source/multiple-entry/rsbuild.config.ts b/e2e/cases/source/multiple-entry/rsbuild.config.ts index 5e2cd7754f..b3c91f1669 100644 --- a/e2e/cases/source/multiple-entry/rsbuild.config.ts +++ b/e2e/cases/source/multiple-entry/rsbuild.config.ts @@ -11,9 +11,6 @@ export default defineConfig({ index: './src/index.client.js', }, }, - output: { - target: 'web', - }, }, node: { source: { @@ -23,9 +20,7 @@ export default defineConfig({ }, output: { target: 'node', - distPath: { - root: 'dist/server', - }, + distPath: 'dist/server', }, }, }, diff --git a/packages/core/src/createContext.ts b/packages/core/src/createContext.ts index b28a47e92a..b3aa141599 100644 --- a/packages/core/src/createContext.ts +++ b/packages/core/src/createContext.ts @@ -10,7 +10,6 @@ import { logger } from './logger'; import type { EnvironmentContext, InternalContext, - NormalizedConfig, NormalizedEnvironmentConfig, ResolvedCreateRsbuildOptions, RsbuildConfig, @@ -18,10 +17,7 @@ import type { RsbuildEntry, } from './types'; -function getAbsoluteDistPath( - cwd: string, - config: RsbuildConfig | NormalizedConfig | NormalizedEnvironmentConfig, -) { +function getAbsoluteDistPath(cwd: string, config: NormalizedEnvironmentConfig) { const dirRoot = config.output?.distPath?.root ?? ROOT_DIST_DIR; return ensureAbsolutePath(cwd, dirRoot); } diff --git a/packages/core/src/defaultConfig.ts b/packages/core/src/defaultConfig.ts index dda3a5e956..1331f61c41 100644 --- a/packages/core/src/defaultConfig.ts +++ b/packages/core/src/defaultConfig.ts @@ -294,8 +294,39 @@ export const withDefaultConfig = async ( }; /** - * Merges user config with default values to ensure required properties - * are initialized. + * Converts a raw config into a consistent object-based structure. + */ +export const normalizeConfigStructure = ( + config: RsbuildConfig, +): RsbuildConfig => { + const { dev, output } = config; + + if (typeof output?.distPath === 'string') { + config = { + ...config, + output: { + ...output, + distPath: { root: output.distPath }, + }, + }; + } + + if (dev?.watchFiles && !Array.isArray(dev.watchFiles)) { + config = { + ...config, + dev: { + ...dev, + watchFiles: [dev.watchFiles], + }, + }; + } + + return config; +}; + +/** + * Normalizes the user configuration by merging it with defaults and ensuring + * consistent structure. */ export const normalizeConfig = (config: RsbuildConfig): NormalizedConfig => { const getMode = (): RsbuildMode => { @@ -313,14 +344,9 @@ export const normalizeConfig = (config: RsbuildConfig): NormalizedConfig => { ...createDefaultConfig(), mode: getMode(), }, - config, + normalizeConfigStructure(config), ) as Required; - const { watchFiles } = mergedConfig.dev as NormalizedDevConfig; - if (!Array.isArray(watchFiles)) { - mergedConfig.dev.watchFiles = [watchFiles]; - } - return mergedConfig as unknown as NormalizedConfig; }; diff --git a/packages/core/src/provider/initConfigs.ts b/packages/core/src/provider/initConfigs.ts index 3e3bd7977d..4ec6d5d7e8 100644 --- a/packages/core/src/provider/initConfigs.ts +++ b/packages/core/src/provider/initConfigs.ts @@ -3,7 +3,11 @@ import { updateContextByNormalizedConfig, updateEnvironmentContext, } from '../createContext'; -import { getDefaultEntry, normalizeConfig } from '../defaultConfig'; +import { + getDefaultEntry, + normalizeConfig, + normalizeConfigStructure, +} from '../defaultConfig'; import { camelCase, color, pick } from '../helpers'; import { ensureAbsolutePath } from '../helpers/path'; import { inspectConfig } from '../inspectConfig'; @@ -12,6 +16,7 @@ import { mergeRsbuildConfig } from '../mergeConfig'; import { initPlugins } from '../pluginManager'; import type { AllowedEnvironmentDevKeys, + EnvironmentConfig, InspectConfigOptions, InternalContext, MergedEnvironmentConfig, @@ -96,7 +101,9 @@ const createEnvironmentNotFoundError = (environments: string[] = []) => { }; const initEnvironmentConfigs = ( - normalizedConfig: NormalizedConfig, + normalizedConfig: Omit & { + environments: Record; + }, rootPath: string, specifiedEnvironments?: string[], ): Record => { @@ -143,10 +150,10 @@ const initEnvironmentConfigs = ( { ...baseConfig, dev: pick(dev, allowedEnvironmentDevKeys), - } as MergedEnvironmentConfig, - config, + }, + normalizeConfigStructure(config), ), - }; + } as unknown as MergedEnvironmentConfig; return [name, applyEnvironmentDefaultConfig(environmentConfig)]; }), diff --git a/packages/core/src/types/config.ts b/packages/core/src/types/config.ts index 0f21a0a0f9..ee3d50ded4 100644 --- a/packages/core/src/types/config.ts +++ b/packages/core/src/types/config.ts @@ -1182,8 +1182,10 @@ export interface OutputConfig { /** * Set the directory of the output files. * Rsbuild will emit files to the specified subdirectory according to the file type. + * - `string`: Set the root output directory to a specific path, equivalent to `distPath.root`. + * - `object`: Set the output directory for each file type. */ - distPath?: DistPathConfig; + distPath?: string | DistPathConfig; /** * Sets the filename of output files. */ diff --git a/website/docs/en/config/output/dist-path.mdx b/website/docs/en/config/output/dist-path.mdx index 525f2fd167..7a8a5bb960 100644 --- a/website/docs/en/config/output/dist-path.mdx +++ b/website/docs/en/config/output/dist-path.mdx @@ -3,21 +3,23 @@ - **Type:** ```ts -type DistPathConfig = { - root?: string; - html?: string; - favicon?: string; - js?: string; - jsAsync?: string; - css?: string; - cssAsync?: string; - svg?: string; - font?: string; - wasm?: string; - image?: string; - media?: string; - assets?: string; -}; +type DistPathConfig = + | string + | { + root?: string; + html?: string; + favicon?: string; + js?: string; + jsAsync?: string; + css?: string; + cssAsync?: string; + svg?: string; + font?: string; + wasm?: string; + image?: string; + media?: string; + assets?: string; + }; ``` - **Default:** @@ -42,6 +44,9 @@ const defaultDistPath = { Configure the directory for output files. Rsbuild outputs files to the specified subdirectory according to file type. +- `string`: Set the root output directory to a specific path, equivalent to `distPath.root`. +- `object`: Set the output directory for each file type. + > See [Output files](/guide/basic/output-files) for more information. ## File types @@ -96,3 +101,10 @@ build │ └── index.js └── index.html ``` + +## Version history + +| Version | Changes | +| ------- | ------------------------------------------- | +| v1.4.13 | Added support for `distPath.favicon` option | +| v1.6.0 | Added support for string type | diff --git a/website/docs/zh/config/output/dist-path.mdx b/website/docs/zh/config/output/dist-path.mdx index dff3db2e5e..ca63aa23b0 100644 --- a/website/docs/zh/config/output/dist-path.mdx +++ b/website/docs/zh/config/output/dist-path.mdx @@ -3,21 +3,23 @@ - **类型:** ```ts -type DistPathConfig = { - root?: string; - html?: string; - favicon?: string; - js?: string; - jsAsync?: string; - css?: string; - cssAsync?: string; - svg?: string; - font?: string; - wasm?: string; - image?: string; - media?: string; - assets?: string; -}; +type DistPathConfig = + | string + | { + root?: string; + html?: string; + favicon?: string; + js?: string; + jsAsync?: string; + css?: string; + cssAsync?: string; + svg?: string; + font?: string; + wasm?: string; + image?: string; + media?: string; + assets?: string; + }; ``` - **默认值:** @@ -42,6 +44,9 @@ const defaultDistPath = { 设置构建产物的输出目录,Rsbuild 会根据产物的类型将其输出到相应的子目录中。 +- `string`:设置根输出目录到指定路径,等同于 `distPath.root`。 +- `object`:为每种文件类型设置输出目录。 + > 查看 [构建产物目录](/guide/basic/output-files) 了解更多。 ## 文件类型 @@ -96,3 +101,10 @@ build │ └── index.js └── index.html ``` + +## 版本历史 + +| 版本 | 变更内容 | +| ------- | ------------------------------------ | +| v1.4.13 | 新增对 `distPath.favicon` 选项的支持 | +| v1.6.0 | 新增对 `string` 类型的支持 |