Skip to content

RFC: Configure devDependencies Release Semantics for Packages #1835

@aui

Description

@aui

Allow configuring which packages' devDependencies changes should trigger version bumps for their dependents.

Motivation

By design, Changesets does not treat devDependencies as part of release semantics. Only when internal runtime dependencies (such as dependencies, peerDependencies, etc.) have version changes will dependent packages be bumped accordingly.

This default behavior is correct and necessary in most scenarios, because: devDependencies typically only affect development, build, and testing processes, not the final artifacts delivered to users.

However, in modern monorepos, there exists a special class of packages that publish "bundled/pre-compiled artifacts" as their release output. In these packages, the above assumption does not hold. Their characteristics include:

  • Publishing bundled JavaScript/CSS instead of source code
  • Build steps are a core part of the release process

For these packages, build-time dependencies are already bundled into the final artifacts, and users don't need these dependencies at runtime. Therefore, declaring them in devDependencies is the correct approach—this prevents users from redundantly installing already-bundled code, reducing dependency tree size.

However, this also introduces a versioning semantic problem: when build-time dependencies in devDependencies change, the final published artifact has already changed, but the package version number remains unchanged. This leads to:

  • Same version number corresponding to different artifacts — breaking version semantics
  • Non-reproducible release results — difficult to rollback
  • Difficult debugging for users — unable to trace changes through versions

Proposed Solution

Add an bumpOnDevDependencies field in .changeset/config.json to explicitly declare which packages' devDependencies changes have release semantics.

Configuration Example

{
  "bumpOnDevDependencies": ["@example/runtime", "@example/design-system"]
}

Semantics

  • When packages in the array are modified, all packages depending on them via devDependencies should publish new versions
  • When packages outside the array are modified, packages depending on them via devDependencies do not need to publish new versions
  • Does not affect dependencies/peerDependencies relationships (handled by existing Changesets mechanism)

Behavior Comparison

After configuration:

@example/runtime (in configuration) is modified
  ↑ devDependencies
@example/app → publish new version ✅

eslint-config (not in configuration) is modified
  ↑ devDependencies
@example/app → do not publish new version ❌

Design Principles

Explicit declaration, opt-in mode

  • Default behavior: devDependencies changes do not trigger version updates (fits most scenarios)
  • Only explicitly configured packages have devDeps release semantics
  • Rationale: bundled packages are a minority in monorepos

Support glob patterns

  • Consistent with existing configurations like ignore
  • Convenient for batch configuration (e.g., @example/*-runtime)

Alternative Solutions Considered

Option A: Declaration in package.json

Add a field in each package's package.json to explicitly express that the current package has bundled dependencies:

{
  "name": "@example/runtime",
  "changeset": {
    "bumpOnDevDependencies": true
  }
}

Or specify concrete dependencies:

{
  "name": "@example/runtime",
  "changeset": {
    "bumpOnDevDependencies": ["@example/compiler", "@example/optimizer"]
  }
}

Pros:

  • ✅ Configuration stays with the package itself, better aligns with "bundled package" being an inherent property
  • ✅ Package maintainers clearly declare their release semantics
  • ✅ Supports finer-grained configuration (specify which devDeps are bundled)

Cons:

  • ❌ Lacks global perspective, difficult to quickly understand which packages in the entire monorepo are bundled
  • ❌ Inconsistent with Changesets design pattern: all configurations are centralized in .changeset/config.json, no precedent for package.json declarations

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions