rolldown icon indicating copy to clipboard operation
rolldown copied to clipboard

[Feature Request]: Avoid duplicated clean dir

Open aprosail opened this issue 2 months ago • 11 comments

What problem does this feature solve?

Avoid duplicated clean dir when multiple outputs like this:

import { defineConfig, OutputOptions } from "rolldown"
import { dts } from "rolldown-plugin-dts"

const input = "src/xxx.ts"
const output: OutputOptions = {
  dir: "out",
  cleanDir: true,
  sourcemap: true,
}

export default defineConfig([
  {
    plugins: [dts({ sourcemap: true })],
    input,
    output: { ...output, format: "esm" },
  },
  {
    input,
    output: {
      ...output,
      format: "commonjs",
      entryFileNames: "[name].cjs",
    },
  },
])

In that case, the second output process will clean the output of the first one.

Definitely, we can set the cleanDir option of the second output to false, which usually works. But that's not safe enough. Perhaps we can add another logic to prevent cleaning the same dir for multiple times.

What does the proposed API look like?

import {defineConfig} from "rolldown"

export default defineConfig({
  ...
  output: {
    cleanDir: true, // true | false | "force".
  }
})
  • false - don't clean dir.
  • true - clean dir but avoid duplicated cleans.
  • "force" - clean dir regardless of whether it had been cleaned during this build.

aprosail avatar Oct 28 '25 07:10 aprosail

It's not difficult to implement such feature. But the question is whether such changes to source code structure and APIs are acceptable:

  1. API changes to the cleanDir type: from boolean to boolean | "force".
  2. Code structure changes to the struct Bundler, which might have potential side effects.
pub struct Bundler {
  ...
  // Append this new property to the Bundler struct.
  pub(crate) cleaned_dirs: Vec<PathBuf>,
}

aprosail avatar Oct 28 '25 08:10 aprosail

I don't see there's a better way to do this. Bundler itself isn't aware of multiple configs. We could do a option validation on nodejs side, emit a warning for such scenario.

hyf0 avatar Oct 28 '25 09:10 hyf0

Bundler itself isn't aware of multiple configs.

Yea, it's much complex than I thought... The Bundler is called by node side rather than rust side, that it's impossible to create something like a mutex to record what dir had been cleaned. Even we can't analysis and cancel the cleanDir config in node side before calling Bundler because there are no strict order on which one cleaned first.

A warning message by analyzing the output dirs before calling the rust side Bundler is definitely possible. But just a warning may not convenient enough for the developers.

How about clean the out dirs in the node side before the bundler is called:

  1. It's easy to avoid duplicated removal, because it won't delete anything during the lifecycle of the rust side bundler.
  2. Node side might a little bit slower than rust, but clean dirs are not performance sensitive operations.
  3. But it separate the clean process from the bundler, which might make the paths error prone.

aprosail avatar Oct 28 '25 11:10 aprosail

Another idea, but might make it more complex:

  1. Keep original rust implementations, and add warning when might be duplicate cleanings.
  2. Add another input options called something like safeCleanOutDirs, default to false.
  3. Once safeCleanOutDirs enabled, it will disable all rust side removals, and resolve everything in node side: detect all dirs to clean and resolve them before the rust side bundler is called using node scripts.

aprosail avatar Oct 28 '25 11:10 aprosail

How about clean the out dirs in the node side before the bundler is called:

Won't consider about this direction due to design principle.


I also see users might want to control different output with separate cleanDir option. So Avoid duplicated clean dir isn't a always pefect behavior.

Things like only avoid removing the same dir when two options resolve to the same dir are too complex. I think keep a simple and intuitive behavior for users to predict is more important.

We could do a option validation on nodejs side, emit a warning for such scenario.

Due to so, raising warning won't be considered too.

hyf0 avatar Oct 28 '25 11:10 hyf0

Writing plugin is also not a good solution to avoid duplicated clean dir, because other plugins might modify the output options that the behavior is also not predictable. That's something only the bundler tool itself can do properly.

Perhaps the following code is a better choice for corresponding scenarios.

const outdirs = [ ... ]
for (const path of outdirs) {
  mkdirSync(path, { recursive: true })
  for (const n of readdirSync(path)) rmSync(join(path, n), { recursive: true })
}

export default defineConfig({
  input: { ... },
  output: { ... },
})

It's just 2 or 5 lines of code, clean and predicable, and easy to maintain in the codebase...

aprosail avatar Oct 28 '25 11:10 aprosail

options get normalized/resolved from rust side, I don't think it could be done easily as you said so.

hyf0 avatar Oct 28 '25 11:10 hyf0

Yes, I'm not sure about that. If that's not something against current design principle, I'll try it later in another Issue&PR when I have enough time (consider that the rust side is more complex).

aprosail avatar Oct 28 '25 13:10 aprosail

To be straight, I don't wanna kill your enthusiasm. But so far I don't see a solid reason for accepting the PR.

hyf0 avatar Oct 28 '25 13:10 hyf0

... Okay, I quit that idea. It's not a serious enthusiasm, I just wanna to solve a (not important) problem in my personal codebase, and there will be many other solutions. Thanks again for your kindness and thoughtful consideration.

aprosail avatar Oct 28 '25 13:10 aprosail

Writing plugin is also not a good solution to avoid duplicated clean dir, because other plugins might modify the output options that the behavior is also not predictable.

I think you can know the final out dir from renderStart hook.

sapphi-red avatar Oct 29 '25 01:10 sapphi-red