Reuse installed framework pins after a lockfile install

Closed
FA
16d ago
+573-17

Split out of #7054. Stacked on #7451 (the npm --save-dev fix), so it targets that branch; only the last commit is this PR.

Changes

After a successful install from the persisted lockfile, framework dependencies from constants.PackageJson.DEPENDENCIES / DEV_DEPENDENCIES whose exact version already sits in the right package.json section are dropped from the follow-up add. npm saves caret ranges, so for npm the declaration is also checked against the package-lock.json entry and the installed package's own package.json before the pin counts as satisfied. Anything that does not verify (non-exact framework specs, explicit conflicting pins, changed overrides, links, aliases, missing manifests) keeps today's add.

Measurement

This is the one from the set I would not merge on the numbers. The add calls still run, because the Radix Themes and Tailwind plugins contribute pinned packages that are always re-added; the PR only shortens their argument lists:

fresh .web, persisted lockfilemainthis PR
bun: packages in the two add calls10 dev + 303 dev + 15
bun: compile phase (includes install)1.15 s1.08 s
npm: compile phase (includes install)8.2 s8.0 s
package-manager commands33

That is within run-to-run noise on this app, for ~190 lines of new logic in js_runtimes.py. The speedup #7054 attributed to this piece on npm was really the --save-dev bug fixed in #7451. I am opening it so the split is complete and the measurement is on record; closing it is a fine outcome.

Measurement setup

Five-page app from the blank template (Radix Themes + Tailwind v4 plugins), Linux x86_64, 4 vCPU, Python 3.14, Node 22.22, npm 10.9, bun 1.4.2. Each run is a fresh interpreter calling reflex.utils.export.export() the same way reflex export does; durations are the phase timings the export already reports to telemetry (compile includes the dependency install). Medians of 3 runs unless noted. Vite dominates every export (~6.5 s); these numbers isolate the part this PR touches.

Type of change

  • Performance improvement (non-breaking)

Checklist

  • Tests added for the change; the full tests/units suite passes locally except the 14 reflex_bench/drivers/test_browser.py cases that need a Playwright browser launch, which fail identically on untouched main in this sandbox
  • ruff check, ruff format --check, codespell, and pyright reflex tests pass locally
  • News fragment added for every package touched

https://claude.ai/code/session_018nWB9r2HcC5tkT72UxWgGj


Generated by Claude Code