Skip to content

minify: 'dce-only' implicitly sets process.env.NODE_ENV to 'production' #8618

@shulaoda

Description

@shulaoda

Description

minify: 'dce-only' (the new default) implicitly sets process.env.NODE_ENV to 'production'. This is an unexpected side effect — the name "dce-only" implies "only perform dead code elimination", but it also switches the entire runtime environment to production mode.

This happens because RawMinifyOptions::is_enabled() returns true for DeadCodeEliminationOnly, and prepare_build_context uses it to determine NODE_ENV:

// crates/rolldown/src/utils/prepare_build_context.rs:165-171
if matches!(platform, Platform::Browser) && !raw_define.contains_key("process.env.NODE_ENV") {
    if raw_minify.is_enabled() {
        raw_define.insert("process.env.NODE_ENV".to_string(), "'production'".to_string());
    } else {
        raw_define.insert("process.env.NODE_ENV".to_string(), "'development'".to_string());
    }
}
// crates/rolldown_common/src/inner_bundler_options/types/minify_options.rs:97-99
pub fn is_enabled(&self) -> bool {
    !matches!(self, Self::Bool(false))
}

Impact

Setting NODE_ENV='production' has broad side effects beyond minification:

  • React/other frameworks resolve to production builds with different APIs and internal structures, e.g., production React removes dispatcher.getOwner() and other development-only internals
  • Library conditional code paths are permanently switched — development warnings, validation, and debugging features are removed at the source level, not by DCE
  • Module Federation shared modules break when host (production React) and remote (development jsx-runtime) have mismatched environment assumptions
  • Third-party packages with process.env.NODE_ENV guards may behave differently than expected during development

Reproduction

// rolldown.config.mjs
export default {
  input: './index.js',
  output: {
    minify: 'dce-only' // or omit entirely, since this is the default
  }
}
// index.js
console.log(process.env.NODE_ENV); // outputs 'production', unexpected for "dce-only"

Discussion

Possible solutions:

  1. dce-only should not auto-set NODE_ENV — add a method like is_production() that returns true only for Bool(true) and Object(...), not for DeadCodeEliminationOnly
  2. Keep current behavior but document it — users can override with define: { 'process.env.NODE_ENV': "'development'" }
  3. Decouple NODE_ENV from minify entirely — make environment mode a separate explicit option

Metadata

Metadata

Labels

dx: missing contextMissing codebase context that slowed down AI-assisted development

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions