Skip to content

fix(build): preserve rolldownOptions proxy (fix #22033)#22367

Closed
maruthang wants to merge 1 commit into
vitejs:mainfrom
maruthang:fix/issue-22033-rolldownoptions-input-proxy
Closed

fix(build): preserve rolldownOptions proxy (fix #22033)#22367
maruthang wants to merge 1 commit into
vitejs:mainfrom
maruthang:fix/issue-22033-rolldownoptions-input-proxy

Conversation

@maruthang

Copy link
Copy Markdown
Contributor

Description

Fixes #22033.

When a builder (or plugin) reassigns the whole build.rolldownOptions object on a resolved environment config, the resulting build ignores the new input and falls back to index.html, producing a chunk named index-*.js instead of entry-*.js.

Root cause. resolveBuildEnvironmentOptions in packages/vite/src/node/build.ts installs a getter/setter proxy via setupRollupOptionCompat(merged, 'build') so that rollupOptions and rolldownOptions stay in sync. The next step builds resolved with { ...merged, ... }. The spread invokes the getter and copies the current value as a plain data property, so resolved.rollupOptions and resolved.rolldownOptions become two independent properties that happen to point at the same object. Once a consumer replaces the whole rolldownOptions, rollupOptions keeps the stale reference; resolveRolldownOptions then reads options.rollupOptions.input (still undefined) and falls back to index.html.

This is why earlier attempts (#22034, #22051) didn't catch it — they didn't identify the proxy-breaking spread.

Fix. Re-install the proxy on resolved after the spread by calling setupRollupOptionCompat(resolved, 'build') again. Six lines of change including a comment that points at #22033.

Alternatives explored

  • Replacing the spread with manual property assignment: more invasive and easy to regress on future refactors.
  • Eagerly reading both fields before the spread and copying both: doesn't fix the underlying problem (later reassignment of one field still desyncs the other).
  • Re-installing the proxy after the spread (this PR): minimal and matches the existing setup pattern.

What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

Testing

  • Added regression test in packages/vite/src/node/__tests__/build.spec.ts that:

    1. Resolves the client environment config,
    2. Reassigns the whole rolldownOptions to { input: '/entry.js' },
    3. Asserts the proxy mirrors the change to rollupOptions.input,
    4. Runs the build and asserts the output chunk filename is entry-*.js (not index-*.js, which would mean a fallback to index.html).

    Verified failing before the fix and passing after.

  • pnpm run test-unit — full suite passes (780 passed, 4 skipped, includes the new test).

  • pnpm run typecheck — passes.

  • pnpm run build — passes.

  • pnpm run lint — clean apart from a pre-existing parse error in playground/preserve-symlinks/module-a/linked.js, which is unrelated to this change.

`resolveBuildEnvironmentOptions` installs a getter/setter proxy via
`setupRollupOptionCompat(merged, 'build')` to keep `rollupOptions` and
`rolldownOptions` in sync, but the subsequent `{ ...merged, ... }`
spread invokes the getter and copies the current value as a plain data
property. After the spread the two fields become independent
references, so when a builder later replaces the whole
`rolldownOptions` object, `rollupOptions` keeps the stale reference and
`resolveRolldownOptions` reads `undefined` for `input`, falling back to
`index.html`.

Re-install the proxy on the resolved options object after the spread to
restore the live link.

fixes vitejs#22033
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Client environment looks for index.html when mutating rolldownOptions.input

1 participant