Modernize repo to use Vite instead of CRA - #576
Conversation
Stage 1: reconcile the react-scripts/node_modules version drift, pin Node 20 LTS (.nvmrc + engines), harden CI (checkout/setup-node v4, --frozen-lockfile), and bump EOL node:10 base images. Stage 2: replace react-scripts (webpack 4, unmaintained) with Vite, and Jest with Vitest, dropping env-cmd and the openssl-legacy-provider workaround entirely. REACT_APP_* env vars renamed to VITE_* throughout. vite-plugin-node-polyfills + commonjsOptions.transformMixedEsModules keep the web3.js/rLogin wallet-connector stack (WalletConnect, Portis, hardware wallet SDKs) working unmodified under Vite's Rollup-based production build. No application logic changed; verified via full test suite, lint, dev server, and all three build variants (testnet/ mainnet/ghpages) with a real wallet-connect flow smoke test. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Enzyme is unmaintained and has no React 18 adapter, which blocks the next stage (React 17 -> 18). Rewrote all 24 Enzyme-based component test files (84 tests) to React Testing Library, using a small shared renderWithProviders() helper (tests/testUtils.js) that wraps RTL's render() in the existing Redux/Router test fixtures (tests/config/ mockStore.js, multiLanguageStore.js) unchanged. Positional/prop-based Enzyme queries (.find(x).at(n), .props().value) were ported to structural DOM queries and jest-dom matchers rather than adding test-ids to production markup, keeping this a test-only change - no non-test src/ files touched. All 10 snapshot files regenerated in Vitest's native DOM format (replacing enzyme-to-json's React-tree dump) and reviewed individually. Found and fixed three pre-existing test bugs along the way: a vacuous always-passing assertion in ToggleComponent, a test-order dependency in UpgradeComponent from a shared mutated wrapper across `it` blocks, and copy-paste residue in LoginFormComponent.test.js. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bumps react/react-dom to ^18 and @testing-library/react to ^16 (all RTL majors 13+ require React 18). src/index.js now uses createRoot and wraps the tree in <React.StrictMode>. Required correctness fixes for a safe StrictMode adoption (behavior- preserving, not new features): - Ported the two componentWillReceiveProps usages (ResolveComponent, DomainStateComponent) to componentDidUpdate. - Fixed two Rules-of-Hooks violations where a hook was called conditionally inside an early-return branch (AdminTabComponent's useEffect, ErrorTabComponent's useState-as-side-effect calling rLoginConnect from within render, worse than the first since lazy initializers run during render, not after). Both moved to an unconditional hook at the top of the component with the original condition preserved inside as a guard - only the calling component's hook structure changed, not rLoginConnect's own wallet-connector logic. - Converted all 22 function-component defaultProps declarations to JS default parameters ahead of the React 18.3+ deprecation, and added `functions: 'defaultArguments'` to the airbnb react/require-default-props ESLint rule so it recognizes the new pattern instead of only the old defaultProps property. Verified with StrictMode active in dev (where double-invoke actually happens) across all main routes and the wallet-connect modal - zero hooks errors, zero wallet-connector regressions. No changes to src/app/auth/operations.js, src/app/rLogin/rLogin.js, or any other wallet-connector logic. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
connected-react-router is unmaintained and has no react-router v6 compatibility path. Its Redux integration turned out to be almost entirely inert plumbing - no reducer ever consumed its LOCATION_CHANGE action; the router slice existed only so components could read location off Redux instead of react-router's own APIs. - react-router/react-router-dom bumped to ^6.30.4, history to ^5.3.0, connected-react-router removed entirely. - App already had a shared `history` singleton (needed for navigating from Redux thunks); wired it into v6 via `unstable_HistoryRouter` instead of `ConnectedRouter`, so all 13 `dispatch(push(path))` call sites became direct `history.push(path)` calls with zero change to when/where navigation happens. - 10 files reading `state.router.location.*` (plus 3 more discovered during implementation via a shared `getSearch` selector with more consumers than the initial grep found) now get location via `useLocation()`, wrapped so the existing mapStateToProps(state, ownProps) shape didn't need restructuring. - `routes.js` and the nested routes in `AdminTabComponent.js` needed real structural changes, not just Switch->Routes renaming: v5's Switch matches first-declared route regardless of specificity, but v6 ranks by path specificity regardless of declaration order. The two conditional path-less <Route> guards (contracts-not-deployed, not-logged-in) were restructured as explicit if/else route-set swaps to preserve the exact original branching - this is react router's own documented pattern for this exact migration case, not a stylistic choice. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…olutions - Removed unused direct dependencies confirmed via full-repo grep: react-add-to-calendar, react-switch, and the explicit react-router entry (react-router-dom already depends on it transitively). - Moved @rsksmart/rns-suite to devDependencies - it's only used by tests/setupRnsSuite.js, never shipped in the app bundle. - Renamed @githubprimer/octicons-react -> @primer/octicons-react (the package moved scopes years ago). The rename coincided with a major version bump in the new scope, so verified the earliest available version (9.6.0) still ships the same Octicon/ getIconByName API before picking it, keeping this a pure rename rather than an unplanned API migration. - Shrank the `resolutions` block from 7 entries to 1: lodash.template, sqlite3, node-sass, and cheerio had zero requesters left anywhere in the dependency tree (vestigial). eslint-utils and @babel/core were actively harmful, not just redundant - both were pinning versions BELOW what the project's own current eslint/ @vitejs/plugin-react already require, so removing them lets those packages resolve to what they actually ask for. Kept the lodash override, which is still needed to force a resolution against an exact-pinned lodash@4.17.15 from @rsksmart/rsk3-utils. Kept styled-components as a direct dependency despite zero usage in src/ - rimble-ui (still actively used) imports it directly and needs it resolvable at the top level of node_modules; removing it broke the build via a hoisting/resolution failure, caught during verification. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Migrates the app from Create React App to Vite, modernizing the build/test toolchain and updating routing/state integration to remove connected-react-router, while also upgrading runtime requirements (Node 20, React 18) and porting unit tests to Vitest + React Testing Library.
Changes:
- Replace CRA build/start/test pipeline with Vite + Vitest (new
vite.config.js, updated scripts, env handling, and CI workflows). - Upgrade React to 18 and React Router to v6; remove
connected-react-routerand refactor navigation/state usage accordingly. - Migrate tests from Enzyme/Jest patterns to React Testing Library + Vitest snapshots and setup.
Reviewed changes
Copilot reviewed 125 out of 126 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.js | Adds Vite config (plugins, build output dir, Vitest setup). |
| tests/vitestSetup.js | Introduces Jest-compat shim for Vitest (global.jest). |
| tests/testUtils.js | Adds RTL helper to render with Redux Provider and optional router. |
| tests/setupTests.js | Replaces Enzyme setup with RTL cleanup + jest-dom for Vitest. |
| tests/setupRnsSuite.js | Updates local test suite setup to use VITE_* env vars. |
| tests/setEnvVars.test.js | Updates env var test to Vite-style import.meta.env. |
| tests/setEnvVars.js | Renames test env vars from REACT_APP_* to VITE_*. |
| tests/config/mockImage.js | Removes Jest image module mock (no longer used). |
| testnet.Dockerfile | Updates base image to Node 20. |
| mainnet.Dockerfile | Updates base image to Node 20. |
| src/serviceWorker.js | Switches CRA env usage to Vite env (import.meta.env). |
| src/index.js | Migrates to React 18 createRoot + StrictMode wrapper. |
| src/configureStore.js | Removes router middleware/reducer wiring; keeps history export; updates env checks for logger. |
| src/app/tabs/SetUpTab.js | Updates env var access to Vite (VITE_ENVIRONMENT_ID). |
| src/app/tabs/search/containers/SearchDomainContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/search/containers/DomainStateContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/search/components/DomainStateComponent.js | Replaces deprecated componentWillReceiveProps with componentDidUpdate. |
| src/app/tabs/resolve/selectors.js | Refactors search selector to take location instead of redux router state. |
| src/app/tabs/resolve/containers/ResolveNameContainer.js | Refactors to pass location via useLocation. |
| src/app/tabs/resolve/containers/ResolveContainer.js | Refactors navigation to use exported history + useLocation. |
| src/app/tabs/resolve/containers/ResolveChainAddrContainer.js | Refactors to pass location via useLocation. |
| src/app/tabs/resolve/containers/ResolveAddrContainer.js | Refactors to pass location via useLocation. |
| src/app/tabs/resolve/components/ResolveComponent.js | Replaces deprecated componentWillReceiveProps with componentDidUpdate. |
| src/app/tabs/resolve/components/ResolveChainAddrComponent.js | Moves default props into function defaults. |
| src/app/tabs/resolve/components/ResolutionComponent.js | Moves default props into function defaults. |
| src/app/tabs/registrar/containers/RevealContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/registrar/containers/RentalPeriodContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/registrar/containers/RegistrarContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/registrar/containers/LoadingContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/registrar/containers/CommitContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/registrar/containers/AutoLoginContainer.js | Refactors navigation to use exported history. |
| src/app/tabs/registrar/components/AutoLoginComponent.test.js | Migrates Enzyme test to RTL + Vitest. |
| src/app/tabs/registrar/components/snapshots/AutoLoginComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/tabs/newAdmin/subdomains/components/SettingsComponent.test.js | Migrates Enzyme test to RTL helpers. |
| src/app/tabs/newAdmin/subdomains/components/NewSubdomainComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/resolver/components/ViewContractAbiComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/resolver/components/NewRecordComponent.test.js | Migrates Enzyme test to RTL helpers + fireEvent. |
| src/app/tabs/newAdmin/resolver/components/snapshots/NewRecordComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/tabs/newAdmin/myurl/components/MyUrlComponent.test.js | Migrates Enzyme/shallow test to RTL helpers. |
| src/app/tabs/newAdmin/myurl/components/MyUrlComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/domainInfo/components/UpgradeComponent.test.js | Migrates Enzyme test to RTL helpers. |
| src/app/tabs/newAdmin/domainInfo/components/TransferSuccessModalComponent.test.js | Migrates Enzyme test to RTL; accounts for portal rendering. |
| src/app/tabs/newAdmin/domainInfo/components/ShareButtonComponent.test.js | Migrates Enzyme test to RTL; accounts for portaled popover content. |
| src/app/tabs/newAdmin/domainInfo/components/ShareButtonComponent.js | Updates share link env var usage to Vite (VITE_URL). |
| src/app/tabs/newAdmin/domainInfo/components/RenewButtonComponent.test.js | Migrates Enzyme test to RTL helpers. |
| src/app/tabs/newAdmin/domainInfo/components/RenewButtonComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/domainInfo/components/DomainInfoComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/domainInfo/components/snapshots/UpgradeComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/tabs/newAdmin/containers/LeftNavContainer.js | Refactors routing/location dependency away from connected-react-router. |
| src/app/tabs/newAdmin/containers/ExpiredDomainContainer.js | Refactors navigation to use exported history. |
| src/app/tabs/newAdmin/components/ReclaimComponent.js | Moves default props into function defaults. |
| src/app/tabs/newAdmin/components/LeftNavComponent.test.js | Migrates Enzyme test to RTL helpers with router wrapper. |
| src/app/tabs/newAdmin/components/AdminTabComponent.js | Updates to React Router v6 <Routes>; refactors effect usage. |
| src/app/tabs/newAdmin/addresses/components/YourAddressesComponent.js | Updates env var usage to Vite; fixes BASE_URL asset paths. |
| src/app/tabs/newAdmin/addresses/components/AddNewAddressComponent.js | Updates env var usage to Vite. |
| src/app/tabs/home/containers/SearchResultsContainer.test.js | Migrates Enzyme test to RTL helpers. |
| src/app/tabs/home/containers/SearchResultsContainer.js | Refactors navigation to use exported history. |
| src/app/tabs/home/containers/SearchBoxContainer.test.js | Migrates Enzyme test to RTL helpers. |
| src/app/tabs/home/components/WalletCarousel.test.js | Migrates Enzyme test to RTL render + DOM queries. |
| src/app/tabs/home/components/SearchResultsComponent.test.js | Migrates Enzyme test to RTL helpers + snapshots. |
| src/app/tabs/home/components/SearchResultsComponent.js | Moves default props into function defaults. |
| src/app/tabs/home/components/SearchBoxComponent.test.js | Migrates Enzyme test to RTL render + fireEvent. |
| src/app/tabs/home/components/snapshots/SearchResultsComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/tabs/home/components/snapshots/SearchBoxComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/tabs/error/ErrorTabContainer.js | Updates env var access to Vite (VITE_ENVIRONMENT_ID). |
| src/app/tabs/error/ErrorTabComponent.js | Fixes incorrect hook usage by switching to useEffect. |
| src/app/selectors.js | Updates env var access to Vite (VITE_ENVIRONMENT_ID). |
| src/app/routes.js | Migrates from Switch/withRouter to React Router v6 <Routes>. |
| src/app/rLogin/rLogin.js | Updates env var access to Vite (VITE_URL, VITE_ENVIRONMENT_ID). |
| src/app/reducers.js | Removes connected-react-router reducer integration. |
| src/app/index.js | Replaces ConnectedRouter with unstable_HistoryRouter. |
| src/app/containers/IndicatorLight.js | Updates env var access to Vite. |
| src/app/containers/GetDomainStateContainer.js | Refactors navigation/location dependency away from redux router state. |
| src/app/components/UserWaitingComponent.test.js | Migrates Enzyme test to RTL. |
| src/app/components/UserWaitingComponent.js | Moves default props into function defaults. |
| src/app/components/UserSuccessComponent.test.js | Migrates Enzyme test to RTL + snapshots. |
| src/app/components/UserSuccessComponent.js | Moves default props into function defaults; updates explorer env var to Vite. |
| src/app/components/UserErrorComponent.test.js | Migrates Enzyme test to RTL + snapshots. |
| src/app/components/UserErrorComponent.js | Moves default props into function defaults. |
| src/app/components/ToggleComponent.test.js | Migrates Enzyme test to RTL + events. |
| src/app/components/ToggleComponent.js | Moves default props into function defaults. |
| src/app/components/TextRotationComponent.test.js | Migrates Enzyme test to RTL + snapshots. |
| src/app/components/TextRotationComponent.js | Moves default props into function defaults. |
| src/app/components/FooterComponent.js | Updates env var usage to Vite (VITE_URL, VITE_GIT_HASH). |
| src/app/components/CopyButtonComponent.test.js | Migrates Enzyme test to RTL + snapshots. |
| src/app/components/CopyableComponent.js | Updates Octicons package import to @primer/octicons-react. |
| src/app/components/AddressInputComponent.test.js | Migrates Enzyme/shallow tests to RTL + Provider wrapper. |
| src/app/components/AddressInputComponent.js | Moves default props into function defaults. |
| src/app/components/snapshots/UserSuccessComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/components/snapshots/UserErrorComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/components/snapshots/ToggleComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/components/snapshots/TextRotationComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/components/snapshots/CopyButtonComponent.test.js.snap | Updates snapshot format for Vitest/RTL. |
| src/app/auth/operations.js | Replaces push actions with direct history.push; updates env var usage to Vite. |
| src/app/auth/containers/StartButtonContainer.js | Replaces push actions with direct history.push. |
| src/app/auth/containers/LoginDropdownContainer.js | Replaces push actions with direct history.push; updates env var usage to Vite. |
| src/app/auth/containers/AuthModalContainer.js | Replaces push actions with direct history.push; updates env var usage to Vite. |
| src/app/auth/components/StartButtonComponent.js | Moves default props into function defaults. |
| src/app/auth/components/SingleDomainComponent.test.js | Migrates Enzyme test to RTL + events. |
| src/app/auth/components/SingleDomainComponent.js | Moves default props into function defaults. |
| src/app/auth/components/LoginFormComponent.test.js | Migrates Enzyme test to RTL + events; aligns names. |
| src/app/auth/components/LoginFormComponent.js | Moves default props into function defaults. |
| src/app/auth/components/LoginDropdownComponent.test.js | Migrates Enzyme test to RTL + events/DOM queries. |
| src/app/auth/components/LoginDropdownComponent.js | Moves default props into function defaults. |
| src/app/adapters/RNSLibAdapter.js | Updates env var access to Vite (VITE_ENVIRONMENT). |
| src/app/adapters/nodeAdapter.js | Updates node URL env var to Vite (VITE_NODE). |
| src/app/adapters/gasPriceAdapter.js | Updates env var access to Vite (VITE_GAS_PRICE). |
| src/app/adapters/explorerAdapter.js | Updates env var access to Vite (VITE_BLOCK_EXPLORER). |
| src/app/adapters/configAdapter.js | Updates env var access to Vite (VITE_ENVIRONMENT). |
| README.md | Updates documented Node version requirement (Node 20). |
| package.json | Replaces CRA with Vite/Vitest; upgrades React/Router; updates dependencies and scripts; adds Node engines. |
| index.html | Updates entrypoint to Vite module script. |
| babel.config.js | Removes Jest/Babel config no longer needed post-migration. |
| .babelrc | Removes Babel config no longer needed post-migration. |
| .nvmrc | Pins Node 20 for local/dev/CI consistency. |
| .github/workflows/qa-deploy.yml | Updates actions versions, uses .nvmrc, switches to VITE_GIT_HASH, enforces frozen lockfile installs. |
| .github/workflows/gh-deploy.yml | Updates actions versions, uses .nvmrc, switches to VITE_GIT_HASH, enforces frozen lockfile installs. |
| .github/workflows/deploy.yml | Updates actions versions, uses .nvmrc, switches to VITE_GIT_HASH, enforces frozen lockfile installs. |
| .github/workflows/ci.yml | Updates actions versions, uses .nvmrc, enforces frozen lockfile installs. |
| .eslintrc.js | Updates parser ecmaVersion; allows default args instead of defaultProps. |
| .env.testnet | Renames CRA env vars to VITE_*. |
| .env.production | Renames CRA env vars to VITE_*. |
| .env.development | Adds Vite-style dev env vars (replaces .env.local). |
| .env.test | Adds Vite-style test env vars for Vitest mode. |
| .env.local | Removes CRA local env file (replaced by Vite env modes). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b55cb206d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Dependency ReviewThe following issues were found:
|
| import React from 'react'; | ||
| import propTypes from 'prop-types'; | ||
| import { Switch, Route, withRouter } from 'react-router'; | ||
| import { Routes as RouterRoutes, Route } from 'react-router-dom'; | ||
| import { connect } from 'react-redux'; | ||
| import { |
| schedule: | ||
| interval: weekly | ||
| # Wait at least 10 days after a new version is released before opening a PR | ||
| cooldown: | ||
| default-days: 5 |
| @@ -1,5 +1,5 @@ | |||
| describe('setEnvVars', () => { | |||
| it('gets correct environment varialbe', () => { | |||
| schedule: | ||
| interval: weekly | ||
| # Wait at least 10 days after a new version is released before opening a PR | ||
| cooldown: | ||
| default-days: 5 | ||
| semver-major-days: 30 | ||
| semver-minor-days: 7 | ||
| semver-patch-days: 3 |
This was a six step plan to migrate the app from CRA to Vite, using AI while attempting to keep the wallet-connector layer (rLogin + WalletConnect v1 + Portis) plus web3.js.
Staged modernization of
rns-manager-react(the RSK/Rootstock Name Service domain manager webapp). Started as a ~5-year-old Create React App project with an unmaintained toolchain, unmaintained test framework, React 17, and an unmaintained router. Six stages completed, each its own commit, each independently verified (full test suite + lint + all three build variants + a Playwright smoke pass) before moving to the next:Why so many files changed?
The ask was to make the minimal changes as possible to get it up to date. That being said, there are
126129 files were changed. Most of them are a few lines, and in thesrcfolder are the following:defaultProps.test.files, there are more changes needed, however, the existing tests all pass and manual tests were performed below.functionality
With the exception of one finding below regarding the search when resolving a domain (adding the starting
/), no functionality was changed.manual tests performed on testnet: