Skip to content

Build1 publisherNot yet confirmed elsewhere3 min readPublished

A build-tool swap that took 70 days and 166 files, and the build was the easy part

The Vite config came to 23 lines. The merge request came to 166 files and 70 days, nearly all of it paying down what Create React App had been quietly supplying.

The Engineer · Build desk

How we use AISend a correction

Illustration accompanying A build-tool swap that took 70 days and 166 files, and the build was the easy part
Generated illustration

What happened

  • A merge request to replace Create React App and Webpack with Vite and SWC on ZURU's DreamNet admin app ran to 166 changed files and 70 days.
  • The app was still on react-scripts 3.0.1, a 2019 release, propped up by rewire, env-cmd and a node-sass build that needed a specific Node version.
  • The Vite config that replaced all of it is 23 lines, using the SWC React plugin and an SVGR plugin.
  • React 18 was left out on purpose: the app stayed on react 16.14.0, ReactDOM.render and react-router-dom 4.3.1.
  • Adding "type": "module" was one line and cost a day, forcing .cjs and .mjs renames plus a wave of .js to .jsx moves.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost Seventy days of one engineer's attention were charged against a change no user can see, and the invoice was dependency archaeology rather than bundler configuration.
  • constraint Refusing the framework upgrade is what kept review cheap: with no intended behaviour change, any difference between the two environments is a defect and nobody has to argue about which deltas were...
  • exposure Any team still on react-scripts 3 is carrying the same undocumented contract in its source, and it stays invisible until the thing satisfying it is removed.
  • precedent Pinning the output directory and port to the old defaults keeps CI, Docker and the deploy scripts ignorant of the swap, which means the migration debt moves into config and waits there for whoever...

The load-bearing sentence in the whole account is that Create React App was never a bundler in the first place, it was an API [16]. Over five years, DreamNet's source had absorbed webpack's semantics: `process.env` reads in browser code, `%PUBLIC_URL%`, `import { ReactComponent as Icon }`, JSX living in `.js` files, implicit Node globals, and automatic Babel transpilation of every CommonJS dependency the team had ever installed [17]. None of those are React features and all of them were holding something up, the author writes [17]. So the first task was not the config file but a survey of every place the source assumed only webpack could satisfy, and that list came out roughly ten times the size of the config [18].

The `constants.js` episode is the mechanism in miniature. It was a data module that had quietly grown JSX inside it, nav configs and ingredient lists and session-OS maps each carrying an `icon: <AacIngredientIcon />` [15]. What exposed it was esbuild's refusal to parse JSX in a `.js` file, which Babel had been doing without complaint [13]. The fix was to split the JSX-bearing exports into `constant.jsx` and leave `constants.js` as data, a change the author says was worth making on its own merits [15]. Note the direction of causation. The new toolchain did not create that mess; it declined to keep concealing it.

Then there is the shape of the review. Twenty-eight or more diff revisions attracted 19 review comments [2], which is fewer than one comment per revision [23], spread across 70 days at roughly one revision every two and a half days [24]. That is not a merge request stuck in an argument. That is one engineer repeatedly finding the next thing the old build had been supplying for free. The 166 changed files also exceed the roughly 130 source files in `src/scene` alone [22], so the blast radius reached well past the screens.

Two things temper the read. This is a single first-person write-up, submitted to DEV's Summer Bug Smash powered by Sentry [21], and the payoff is stated as intent rather than measurement: faster cold start, near-instant HMR, better production builds [19]. The old feedback loop is described in units of checking Slack and, on a cold start, making coffee [20]. Anyone approving this work on those grounds is buying 70 days of attention against a number nobody in the account has yet published.

The transferable part is the discipline around the deployment contract. Vite defaults to `dist` and port 5173, but the GitLab CI jobs, Docker image and deploy scripts expected `build/` on port 3000, so both were pinned in config [7]. The author's rule: absorb the churn in configuration, not in infrastructure, because changing the bundler and the deployment contract together produces a broken pipeline you cannot attribute to either [8].

What to watch

  • Whether a follow-up MR takes React 18 and the router upgrade now that the .jsx boundaries have already been drawn, and how many files it touches.
  • Any published before-and-after timings for cold start and HMR, which the write-up promises as intent but does not measure.
  • Post-cutover regression reports: the account ends at green on production, not after a week of live traffic.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence54
Adoption24
Hype gap+8
Incentives41
Confidence49
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    MR !907 migrated DreamNet from Create React App plus Webpack to Vite plus SWC: 166 changed files and 70 days between the proposal to swap the bundler and green on production.

  2. [2]

    MR !907 carried 28 or more diff revisions and 19 review comments.

    ReportedSupportedView cited source
  3. [3]

    DreamNet is the internal admin platform for ZURU's housing division, covering user management, RBAC, asset catalogues, project publishing, release builds, an order-pricing engine, event management and dashboards with charts and maps.

    ReportedSupportedView cited source

Sources

1 independent publisher whose own reporting we read for this story.

  1. dev.to

    1 article · August 23, 2026

    Migrating a 5-year-old React admin app from CRA + Webpack to Vite + SWC — 166 files, 70 days

Share your take

Let Clarity write the post for you.

Signed-in readers get a short post drafted on this story in the register they choose — narrative, analytical, or a direct position — editable to the last word before it goes anywhere. The share buttons at the top of this story work without an account.

Topics and entities

Follow any of these and your For You feed starts watching them — no settings page required.

Topics

  • Build Tool MigrationFollow
  • Legacy Frontend ModernisationFollow
  • ESM and Module SemanticsFollow
  • Build-Time Environment ConfigurationFollow
  • Migration Scope DisciplineFollow
Loading related stories