Conversation
No source imports jquery anywhere in client/.
node-sass is deprecated and fails to build on Node 18+. Dart sass is the official successor and is a drop-in for the @import/@use syntax already in src/scss/.
IE11 reached end-of-life in 2022. Removing the polyfill imports and the "ie 11" entry from browserslist.development reduces bundle weight and unblocks the move off CRA.
The CRA-generated serviceWorker.js was only ever called via unregister(); it has never registered a worker. Removing the file and its import.
vite + @vitejs/plugin-react replace react-scripts as the build tool. Config ports the dev proxy from src/setupProxy.js (which is removed in a later commit alongside react-scripts itself), honors GENERATE_SOURCEMAP from .env.production, and pins build.outDir to 'build' so the existing Dockerfile/nginx pipeline keeps working unchanged. The REACT_APP_ env prefix is preserved here; renames to VITE_ land in a follow-up commit so the env-var migration is reviewable in isolation.
Vite's React plugin requires a .jsx extension on files containing JSX syntax (CRA was forgiving here). Pure rename, no content change.
Vite expects index.html at the project root (rather than public/) and treats it as the build entry. Files in public/ are still served at the URL root, so absolute paths like /images/... and /js/env.config.js continue to resolve. Also adds the <script type="module" src="/src/index.jsx"> tag that Vite uses as the module graph entry, and trims CRA-era boilerplate comments.
Replace %PUBLIC_URL%/... refs (CRA template syntax) with absolute paths. Files in public/ are still served at the URL root by Vite, so /images/..., /manifest.json, and /js/env.config.js continue to resolve. Add <script type="module" src="/src/index.jsx"> as Vite's module-graph entry, and trim CRA-era boilerplate comments.
Vite only exposes env vars prefixed with VITE_ to the client bundle (via import.meta.env). Renaming the build-time env vars and their consumers in Constants.js and Keycloak.js. Also drops the BROWSER=none CRA-ism (Vite doesn't auto-open the browser). The runtime-injected window.RUNTIME_REACT_APP_* globals (set by nginx-start/start.sh at container startup) are deliberately untouched — they live outside the build and are how prod environments override host/realm/client without rebuilding.
PUBLIC_URL was a CRA build-time placeholder. Vite serves the public
directory at the URL root, so absolute paths like /images/... and the
default browser-history basename ('/') are equivalent.
CRA is fully replaced. Drops: - react-scripts dep - src/setupProxy.js (proxy now lives in vite.config.js server.proxy) - eslintConfig.extends="react-app" (CRA-specific preset) - overrides.autoprefixer (transitive CRA pin, no effect once webpack chain is gone) - "test" and "eject" scripts (no test infra; nothing to eject from) The "start" script is kept (mapped to "vite") so `npm start` keeps working for anyone wired to the CRA convention. Adds "preview" for testing the production build locally. The Dockerfile keeps invoking `npm run build` unchanged.
Was pinned to v10.15.2 (2019), four LTS lines behind. Node 18 reached EOL in April 2025 and Node 20 in April 2026, so anything older than 22 is unsupported. Going to 24 (current active LTS, supported until April 2028) to match local dev and the planned d3d940-tools/node ImageStream update.
Result of `npm install` against the rewritten package.json. Tree size drops from CRA's webpack/jest sprawl to 276 packages. Audit reports 10 vulns (3 moderate, 7 high), down from 72 in pre-upgrade-log.txt; the bulk of CRA-only transitive vulns are already gone. Remaining vulns will be cleaned up in chunks B/E.
CRA was lenient about file extensions and accepted JSX inside .js files;
the codebase relies on this in ~50 components. Vite's defaults are
stricter: esbuild's dep scanner picks a loader from the extension and
fails on JSX in .js, and the React plugin only transforms .jsx by
default.
Two-part fix:
- plugins: [react({ include: /\.(js|jsx)$/ })] — the React plugin's
Babel transform now runs on .js files too, so HMR works.
- optimizeDeps.esbuildOptions.loader = { '.js': 'jsx' } — the dep
pre-bundler scans .js files as JSX, unblocking startup.
A future cleanup could rename JSX-bearing .js files to .jsx, but that's
out of scope for the migration.
The earlier dev-mode fix only patched optimizeDeps' esbuild scanner. Production builds use Rollup, where the React plugin's babel transform wasn't reaching .js files in time for vite:build-import-analysis. Adding esbuild.loader='jsx' with include=src/**/*.jsx? makes Vite's esbuild transform run on .js files there too, producing valid JS before import-analysis sees it. Also reverts the redundant include override on react() — its default filter (/\.[jt]sx?$/) already matches .js files.
The leading ~ was a webpack/sass-loader convention that resolved bare specifiers from node_modules. Vite's sass integration uses standard module resolution, so the unprefixed path is what works. Without this change, sass errors with "Can't find stylesheet to import."
The MyriadWebPro font files moved from src/fonts/ (committed earlier) to public/fonts/ so they are served as plain static assets — same pattern as public/images/. The SCSS \$bcgov-font-path now points at the absolute /fonts/ URL instead of a relative ../../fonts/ path. Without this, vite build couldn't resolve the relative font references through Sass's variable interpolation and would emit them unchanged, producing 404s at runtime.
…piAccess The Async Clipboard API (navigator.clipboard.writeText) is supported by every browser we still target (IE11 was dropped earlier in this chunk). Both copy buttons now use a Reactstrap Button that awaits writeText and fires the existing toast on success — same UX, no extra dep.
…ubmission detail Same swap as ApiAccess: Reactstrap Button + navigator.clipboard.writeText. The "Copy errors to clipboard" action in the submission-detail modal now uses the native API instead of react-clipboard.js.
Both consumers were migrated in earlier commits.
Replacement for the abandoned react-dates. Peer-deps React 16-19, so compatible with the current React 16 baseline. Lock file is regenerated at the end of this chunk.
… SingleDateField
react-datepicker uses native Date objects rather than moment. The
wrapper translates at the boundary so callers (Formik values stored as
moment) don't need to change. The isOutsideRange (moment) prop is
adapted to react-datepicker's filterDate (Date) by inverting the
predicate and converting back to moment for the caller's logic.
UX deltas vs react-dates:
- Date format string syntax changes ('YYYY-MM-DD' moment -> 'yyyy-MM-dd'
date-fns).
- The "default input icon" and explicit clear button are replaced by
react-datepicker's built-in clearable affordance (isClearable).
- The "focused" class wrapper is dropped — react-datepicker has its own
popover/focus styling.
… DeleteButton Same translation pattern as SingleDateField — moment <-> Date at the picker boundary, drop the manual focus-state tracking. Local component state (not Formik) so no schema changes required.
… fields in DateRangeField react-datepicker doesn't have a unified two-field range picker, but its selectsStart / selectsEnd props on two separate pickers preserve the two-input UX from before (Date From / Date To). The pickers share a range view via startDate/endDate, and the second picker's minDate is bound to the first so the user can't pick an end before the start. Validation surface unchanged: still uses Formik's errors[fromName] || errors[toName] and renders FormFeedback. Drops the local "touched" tracking and visual focusedInput class — react-datepicker handles its own focus styling, and submitCount alone is enough to gate the error display once Formik has been submitted.
…WorkReportingSubmissions The inline submission-search range filter was the last react-dates consumer. Same selectsStart/selectsEnd two-picker pattern as DateRangeField, but binding to local React state and triggering the existing handleDateChanged so search results refresh on every change. The startDateLimit + future-date guard (was isOutsideRange) is rewritten as filterDate, with moment(date) wrapping to keep the existing date math.
All five react-dates consumers were migrated in earlier commits. This finishes the removal: - App.js drops react-dates/initialize and the bundled CSS, replaces with react-datepicker/dist/react-datepicker.css. - _datepicker.scss is rewritten from 136 lines of react-dates DOM styling to a minimal react-datepicker theme that preserves the primary/info color scheme for selected days and ranges. - react-dates removed from package.json.
The original package was deprecated and explicitly redirected to @redux-devtools/extension (npm warned about this on every install). The /developmentOnly subpath and composeWithDevTools API are unchanged, so store.js needs only the import path updated.
…velopmentOnly The new @redux-devtools/extension@3.x doesn't expose a top-level /developmentOnly export like the legacy redux-devtools-extension did; the actual file is at lib/esm/developmentOnly.js and the package.json has no exports map to alias it. Pointing the import directly at the ESM path so Rollup can resolve it.
Net change from npm install: - removed 74 packages (react-dates and its airbnb-prop-types/moment- range tree, react-clipboard.js, redux-devtools-extension) - added 13 packages (react-datepicker + date-fns, @redux-devtools/ extension) - audit: 9 vulnerabilities (down from 10)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
rogene-bcgov
approved these changes
May 12, 2026
| @@ -1 +1 @@ | |||
| v10.15.2 No newline at end of file | |||
| 24 | |||
Collaborator
There was a problem hiding this comment.
Is this supposed to be 24 or 25?
This reverts commit 793a4ce.
We can’t have 15 due to compliance issues Signed-off-by: Ionwyn Sean <ionwynsean@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.