Skip to content

Migrate from Create React App to Vite and upgrade to React 19#19

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1778516557-migrate-vite-react19
Open

Migrate from Create React App to Vite and upgrade to React 19#19
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1778516557-migrate-vite-react19

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented May 11, 2026

Summary

Migrates the project off the unmaintained react-scripts (CRA) toolchain onto Vite, and upgrades the runtime to React 19 along with related testing and icon libraries.

Build tooling: CRA → Vite

  • Removed react-scripts, added vite ^8.0.12, @vitejs/plugin-react ^6.0.1.
  • New vite.config.js at the repo root with:
    • Path aliases for components, constants, context, hooks, lib, styles (replicating CRA's jsconfig.json baseUrl: src behaviour so existing absolute imports keep working).
    • server.port: 3000 to preserve the previous dev URL.
    • Inline Vitest config (environment: 'jsdom', globals: true, setupFiles: './src/setupTests.js').
  • Moved public/index.html → repo root index.html. Replaced %PUBLIC_URL% references with absolute paths and added <script type="module" src="/src/index.jsx">.
  • Renamed src/index.jssrc/index.jsx (Vite/rolldown require explicit JSX extensions).
  • Also renamed src/context/AlertContext.jssrc/context/AlertContext.jsx — the build failed without it because rolldown doesn't transpile JSX inside .js files (the other .js files in src/hooks/ don't contain JSX, so they were left alone).
  • Updated package.json scripts: startvite, buildvite build, testvitest, plus a new previewvite preview. Removed the CRA-specific eslintConfig and browserslist blocks. Added "type": "module" (required for ESM vite.config.js).
  • Added /dist to .gitignore.

React 19

  • Bumped react and react-dom to ^19.0.0.
  • Rewrote src/index.jsx to use createRoot from react-dom/client instead of the legacy ReactDOM.render.
  • src/components/Modal/Modal.jsx and src/components/Alert/Alert.jsx: added a nodeRef to each CSSTransition so react-transition-group no longer relies on findDOMNode (removed in React 19). react-transition-group is still v4 (no v5 published yet); the nodeRef approach is the documented fix.

Testing: Jest (via CRA) → Vitest

  • Added vitest ^4.1.6 and jsdom ^29.1.1 as dev deps.
  • Upgraded @testing-library/react to ^16.3.2, @testing-library/jest-dom to ^6.9.1, @testing-library/user-event to ^14.6.1.
  • src/setupTests.js now imports @testing-library/jest-dom/vitest (the v6 entrypoint that wires matchers into Vitest's expect).
  • src/App.test.jsx previously asserted on "learn react" text (CRA boilerplate that never matched anything in this app). Rewrote it as a real smoke test that renders <App /> wrapped in <AlertProvider> and asserts the container isn't empty.

Other dependency upgrades

  • react-icons ^4.3.1^5.6.0 (compatible with React 19).
  • react-countdown ^2.3.2^2.3.6 (latest, supports React 19).
  • web-vitals ^2.1.4^5.2.0. Updated src/reportWebVitals.js to use the v3+ API (onCLS, onINP, onFCP, onLCP, onTTFB) — the v2 functions getFID, getCLS, etc. no longer exist in v5, so the file would otherwise crash at runtime as soon as reportWebVitals(console.log) was called.

Verification

  • npm install → clean install (216 packages, 0 vulnerabilities).
  • npm run check (Prettier) → all files formatted.
  • npm run buildvite build succeeds (dist/index.html + assets emitted).
  • npx vitest run → 1 test passes.
  • npm start (Vite dev server on http://localhost:3000) → app loads, board renders, keyboard renders, welcome modal animates in. No console errors.

Screenshot of the running dev server (Vite, React 19) before the welcome modal appears:

Wordle running on Vite + React 19

Review & Testing Checklist for Human

Risk level: yellow — large dependency bump and toolchain swap, but functional surface area of the app is small and the smoke test + manual run looked good.

  • npm install && npm start, then play a full game: type guesses, submit with Enter, verify the row flip animation runs and the keyboard highlights correctly. Open the Stats, Settings, and How to play modals — each one should fade in and the click-outside behaviour should still close them (this is the CSSTransition + nodeRef path).
  • Verify the Alert banner still slides in/out on errors (e.g. submit a 3-letter guess to trigger "Not enough letters", or a non-dictionary word to trigger "Not in word list").
  • npm run build && npm run preview and confirm the production bundle behaves identically — Vite's prod build is a different code path than dev.
  • Confirm localStorage persistence still works (refresh after a guess; the row should still be filled in).

Notes

  • react-transition-group does not yet have a v5; v4.4.5 + nodeRef is the React 19-compatible path.
  • "type": "module" was added to package.json so vite.config.js can be authored as ESM (uses import syntax). This shouldn't affect anything else in this project since there are no CommonJS scripts.
  • I intentionally left jsconfig.json in place — it still helps editors resolve the path aliases even though Vite no longer reads it.
  • The CRA src/App.test.jsx was a boilerplate test that asserted on text (/learn react/i) that has never existed in this app — it would have failed under either toolchain. Replaced with a smoke test rather than deleted so npm test continues to exercise something real.

Link to Devin session: https://app.devin.ai/sessions/9ac47575d81b421d9a0ea23513ca0609
Requested by: @vanessasalas-cog


Devin Review

Status Commit
⚪ Not started

Run Devin Review

💡 Connect your GitHub account to enable automatic code reviews.

Open in Devin Review (Staging)

- Replace react-scripts with vite, @vitejs/plugin-react, vitest, jsdom
- Add vite.config.js with src/* path aliases and vitest config (jsdom env)
- Move public/index.html -> index.html, add <script type="module" src="/src/index.jsx">
- Rename src/index.js -> src/index.jsx and switch to ReactDOM createRoot
- Upgrade React/ReactDOM to ^19.0.0
- Pass nodeRef to CSSTransition in Modal and Alert (React 19 dropped findDOMNode)
- Upgrade @testing-library/react ^16, @testing-library/jest-dom ^6, user-event ^14
- Use @testing-library/jest-dom/vitest in src/setupTests.js
- Rewrite src/App.test.jsx to wrap App in AlertProvider (CRA boilerplate test removed)
- Rename src/context/AlertContext.js -> .jsx (Vite/rolldown won't transform JSX in .js)
- Upgrade react-icons to ^5, react-countdown to ^2.3.6, web-vitals to ^5
  and migrate reportWebVitals to web-vitals v5 onCLS/onINP/onFCP/onLCP/onTTFB API
- Drop CRA-specific eslintConfig and browserslist from package.json
- Add /dist to .gitignore

Co-Authored-By: vanessa.salas <vanessa.salas@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

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.

1 participant