diff --git a/e2e/cases/output/clean-dist-path/index.test.ts b/e2e/cases/output/clean-dist-path/index.test.ts index 2d3b148291..fcfb9c831b 100644 --- a/e2e/cases/output/clean-dist-path/index.test.ts +++ b/e2e/cases/output/clean-dist-path/index.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { join } from 'node:path'; -import { build, proxyConsole } from '@e2e/helper'; +import { build, dev, proxyConsole } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import fse from 'fs-extra'; @@ -16,9 +16,39 @@ test('should clean dist path by default', async () => { }); expect(fs.existsSync(testDistFile)).toBeFalsy(); +}); + +test('should not clean dist path in dev mode when writeToDisk is false', async () => { + await fse.outputFile(testDistFile, `{ "test": 1 }`); + + await dev({ + cwd, + rsbuildConfig: { + dev: { + writeToDisk: false, + }, + }, + }); + + expect(fs.existsSync(testDistFile)).toBeTruthy(); fs.rmSync(testDistFile, { force: true }); }); +test('should clean dist path in dev mode when writeToDisk is true', async () => { + await fse.outputFile(testDistFile, `{ "test": 1 }`); + + await dev({ + cwd, + rsbuildConfig: { + dev: { + writeToDisk: true, + }, + }, + }); + + expect(fs.existsSync(testDistFile)).toBeFalsy(); +}); + test('should not clean dist path if it is outside root', async () => { const { logs, restore } = proxyConsole(); const testOutsideFile = join(cwd, '../node_modules/test.json'); diff --git a/packages/core/src/plugins/cleanOutput.ts b/packages/core/src/plugins/cleanOutput.ts index 0543969230..c2da30b8a7 100644 --- a/packages/core/src/plugins/cleanOutput.ts +++ b/packages/core/src/plugins/cleanOutput.ts @@ -66,6 +66,7 @@ export const pluginCleanOutput = (): RsbuildPlugin => ({ const getPathInfo = ( environment: EnvironmentContext, + isDev?: boolean, ): PathInfo | undefined => { const { rootPath } = api.context; const { config, distPath } = environment; @@ -73,8 +74,13 @@ export const pluginCleanOutput = (): RsbuildPlugin => ({ config.output.cleanDistPath, ); - // only enable cleanDistPath when the dist path is a subdir of root path if (enable === 'auto') { + // If no files are written to disk, we don't need to clean the output + if (isDev && !config.dev.writeToDisk) { + return undefined; + } + + // only clean when the dist path is a subdir of root path if (isStrictSubdir(rootPath, distPath)) { return { path: distPath, @@ -105,6 +111,7 @@ export const pluginCleanOutput = (): RsbuildPlugin => ({ const cleanAll = async (params: { environments: Record; + isDev?: boolean; }) => { // dedupe environments by distPath const environments = Object.values(params.environments).reduce< @@ -117,7 +124,9 @@ export const pluginCleanOutput = (): RsbuildPlugin => ({ }, []); const pathInfos: PathInfo[] = [ - ...environments.map(getPathInfo), + ...environments.map((environment) => + getPathInfo(environment, params.isDev), + ), getRsbuildOutputPath(), ].filter((pathInfo): pathInfo is PathInfo => !!pathInfo); @@ -132,6 +141,9 @@ export const pluginCleanOutput = (): RsbuildPlugin => ({ await cleanAll({ environments }); } }); - api.onBeforeStartDevServer(cleanAll); + + api.onBeforeStartDevServer(async ({ environments }) => { + await cleanAll({ environments, isDev: true }); + }); }, }); diff --git a/website/docs/en/config/output/clean-dist-path.mdx b/website/docs/en/config/output/clean-dist-path.mdx index 1e6ecb0732..42d9bf32a2 100644 --- a/website/docs/en/config/output/clean-dist-path.mdx +++ b/website/docs/en/config/output/clean-dist-path.mdx @@ -8,13 +8,14 @@ type CleanDistPath = boolean | 'auto' | CleanDistPathObject; - **Default:** `'auto'` -Whether to clean up all files under the output directory before the build starts (the output directory defaults to `dist`). +Whether to clean up all files under the output directory before the build starts, the output directory is the value of [output.distPath.root](/config/output/dist-path). ## Default behavior -The default value of `output.cleanDistPath` is `'auto'`. If the output directory is a subdir of the project root path, Rsbuild will automatically clean all files under the output directory. +The default value of `output.cleanDistPath` is `'auto'`: -When [output.distPath.root](/config/output/dist-path) is an external directory, or equals to the project root directory, `cleanDistPath` is not enabled by default, to avoid accidentally deleting files from other directories. +- In development mode, if the value of [dev.writeToDisk](/config/dev/write-to-disk) is `false`, Rsbuild will not perform cleanup. +- In any mode, if [output.distPath.root](/config/output/dist-path) is an external directory or equals to the project root directory, Rsbuild will not perform cleanup to avoid accidentally deleting files from other directories. ```js export default { diff --git a/website/docs/zh/config/output/clean-dist-path.mdx b/website/docs/zh/config/output/clean-dist-path.mdx index 96610891fc..401abe2187 100644 --- a/website/docs/zh/config/output/clean-dist-path.mdx +++ b/website/docs/zh/config/output/clean-dist-path.mdx @@ -8,13 +8,14 @@ type CleanDistPath = boolean | 'auto' | CleanDistPathObject; - **默认值:** `'auto'` -是否在构建开始前清理产物目录下的所有文件(产物目录默认为 `dist`)。 +是否在构建开始前清理产物目录下的所有文件,产物目录为 [output.distPath.root](/config/output/dist-path) 的值。 ## 默认行为 -`output.cleanDistPath` 的默认值为 `'auto'`。如果产物目录是项目根路径的子目录,Rsbuild 会自动清空产物目录下的文件。 +`output.cleanDistPath` 的默认值为 `'auto'`: -当 [output.distPath.root](/config/output/dist-path) 为外部目录,或等于项目根目录时,`cleanDistPath` 不会默认开启,这是为了避免误删其他目录的文件。 +- 在开发模式下,如果 [dev.writeToDisk](/config/dev/write-to-disk) 的值为 `false`,则 Rsbuild 不会执行清理。 +- 在任意模式下,如果 [output.distPath.root](/config/output/dist-path) 为外部目录,或等于项目根目录时,Rsbuild 不会执行清理,这是为了避免误删其他目录的文件。 ```js export default {