docs: record react-* modernization (helmet/i18n/bootstrap/router) + deferred leaflet & BS5

UPGRADE.md dependency-debt table and PENDIENTE.md updated to reflect the
5 shipped phases and the two deferred sub-projects (react-leaflet 1.8->4
and the Bootstrap 4->5 CSS/JS jump), with rationale for each deferral.
Final state: helmet/i18next/react-bootstrap/react-router warnings all
gone from the console; only react-leaflet (deferred) and our own
defaultProps/findDOMNode remain. REST smoke byte-identical.
This commit is contained in:
vjrj 2026-07-21 13:05:05 +02:00
parent e2d13ca64c
commit 6e28bf3545
2 changed files with 35 additions and 19 deletions

View file

@ -9,19 +9,23 @@ Lo que falta, agrupado. Ver `UPGRADE.md` para el detalle de lo ya hecho.
## 1. Modernización de librerías react-* antiguas (deuda de front grande) ## 1. Modernización de librerías react-* antiguas (deuda de front grande)
Funcionan en React 18 por compatibilidad heredada, pero ensucian la consola en Funcionan en React 18 por compatibilidad heredada, pero ensucian la consola en
desarrollo (no en producción) y **bloquean el salto a React 19**. Orden y riesgo: desarrollo (no en producción) y **bloquean el salto a React 19**. Estado:
| Lib | Actual | Objetivo | Riesgo | | Lib | De → A | Estado |
|---|---|---|---| |---|---|---|
| react-helmet | 5.2 | react-helmet-async | bajo | | react-helmet | 5.2 → react-helmet-async 2 | ✅ hecho |
| react-i18next + i18next | 7.4 / 10.5 | 11+ / moderno | medio (mecánico, muchos ficheros) | | react-i18next + i18next | 7.4/10.5 → 14/23 | ✅ hecho |
| react-bootstrap + reactstrap | 0.31 / 5.0-alpha | 2 / 9 | alto (Bootstrap 3→5, renombra componentes y **afecta al SCSS**) | | react-bootstrap | 0.31 → 2 | ✅ hecho (CSS sigue en Bootstrap 4) |
| react-router-dom | 4.2 | 6/7 | **alto** (API totalmente distinta) | | reactstrap + 3 deps muertas | — | ✅ eliminadas (0 usos) |
| react-leaflet + leaflet | 1.8 / 1.3 | 4 / moderno | **alto** (reescritura hooks, sin `leafletElement`/refs) | | react-router-dom | 4.2 → 6.30 | ✅ hecho (history 5, HOC `withRouterCompat`) |
| **react-leaflet + leaflet** | 1.8/1.3 → 4/1.9 | ⏸️ **diferida** (mapa = feature central; 4 plugins v1-only sin equivalente v4; ver UPGRADE.md) |
| **Bootstrap CSS/JS** | 4.1 → 5 | ⏸️ **diferida** (carrusel/navbar jQuery BS4; ver UPGRADE.md) |
Prompt de arranque preparado (pedir al asistente "el prompt de las libs react"). Lo verificado en navegador tras cada lib: `/`, `/fires`, `/fire/archive/<hex>`,
El smoke REST **no cubre** nada de esto → la red real es la verificación visual `/login`, `/subscriptions` + consola. Los warnings de librería que bloqueaban
en navegador (rutas: `/`, `/fires`, `/fire/archive/<hex>`, `/login`, `/subscriptions`). React 19 quedan reducidos a: react-leaflet (diferida) y código propio
(`defaultProps` en componentes función, un `findDOMNode` en blaze-react-component).
El smoke REST siguió byte-idéntico en cada paso.
--- ---
@ -45,9 +49,14 @@ en navegador (rutas: `/`, `/fires`, `/fire/archive/<hex>`, `/login`, `/subscript
- **i18n de cuentas (`meteor-accounts-t9n`, T9n):** paquete antiguo aún usado - **i18n de cuentas (`meteor-accounts-t9n`, T9n):** paquete antiguo aún usado
(Login, VerifyEmail, i18n). Verificar que funciona en Meteor 3; traducción (Login, VerifyEmail, i18n). Verificar que funciona en Meteor 3; traducción
gallega (gl) incompleta (varios TODO en `i18n.js`). gallega (gl) incompleta (varios TODO en `i18n.js`).
- **SCSS acoplado a Bootstrap 3:** al subir react-bootstrap a v2 (Bootstrap 5), - **Salto Bootstrap 4→5 (CSS/JS) pendiente:** react-bootstrap ya está en v2 y
revisar `new-age.scss`, `custom.scss`, `bootstrap-overrides.scss` y las clases corre sobre el CSS Bootstrap 4 actual (`alexwine:bootstrap-4`) con un único
de layout (Grid/Row/Col). shim `.form-label` en `forms.scss`. El salto a Bootstrap 5 npm está diferido
porque el carrusel del home (`bootstrap-carousel-swipe`, jQuery/BS4) y el
collapse del navbar dependen del JS jQuery de BS4 (`data-toggle`, `data-slide`).
Al hacerlo: importar `bootstrap@5` SCSS+JS, reescribir el carrusel (BS5 trae
swipe nativo → quitar el plugin), `data-toggle``data-bs-toggle`,
`ml-auto``ms-auto`, revisar `new-age.scss`/`custom.scss`/`bootstrap-overrides.scss`.
- **Limpieza menor:** migración 217 `// TODO remove falsepositives lowercase - **Limpieza menor:** migración 217 `// TODO remove falsepositives lowercase
collection`; `prerender.js` gating comentado; sección per-fire del sitemap collection`; `prerender.js` gating comentado; sección per-fire del sitemap
eliminada (era código muerto tras `firesMapEnabled=false`). eliminada (era código muerto tras `firesMapEnabled=false`).

View file

@ -291,9 +291,16 @@ MONGO_CONTAINER=tcef-mongo7 MONGO_SHELL=mongosh MONGO_PORT=27019 ./smoke/smoke.s
a watched file). Stop the server (or restart it after) when touching deps. a watched file). Stop the server (or restart it after) when touching deps.
### Still TODO before the web (not just REST) is fully deployable on 3.x ### Still TODO before the web (not just REST) is fully deployable on 3.x
- **React 16 → 18** render root + verify ancient react-* libs. - ✅ **React 16 → 18** render root + ancient react-* libs modernized: react-helmet→
- Re-enable dev fixtures / sitemaps / email default template with async ports. react-helmet-async, i18next 10→23 + react-i18next 7→14, react-bootstrap 0.31→2,
- SCSS `@import``@use`, `lighten`/`darken``color.adjust` (dart-sass deprecations). react-router-dom 4→6. Dead deps (reactstrap, react-leaflet-sidebarv2,
react-router-hash-link, react-addons-pure-render-mixin) dropped. All
browser-verified, REST smoke byte-identical. **Remaining front debt:**
react-leaflet 1.8→4 (deferred — core map, 4 v1-only plugins) and the
Bootstrap 4→5 CSS/JS jump (deferred — jQuery carousel/navbar). Both are what's
left before a React 19 jump.
- ✅ Re-enabled dev fixtures / sitemaps / email default template with async ports.
- ✅ SCSS `@import``@use`, `lighten`/`darken``color.adjust` (dart-sass deprecations).
- **Production cutover** still needs: Mongo data migrated 3.2→7 (mongodump/restore), - **Production cutover** still needs: Mongo data migrated 3.2→7 (mongodump/restore),
the notifications service emitting in prod, and the Docker deployment (fase 3). the notifications service emitting in prod, and the Docker deployment (fase 3).
@ -301,7 +308,7 @@ MONGO_CONTAINER=tcef-mongo7 MONGO_SHELL=mongosh MONGO_PORT=27019 ./smoke/smoke.s
| Dep | From | Target | Status | | Dep | From | Target | Status |
|---|---|---|---| |---|---|---|---|
| React / react-dom | 16.0 | 18 | ✅ done — 18.3.1 + createRoot; ancient react-* libs work on 18 via legacy context (die on 19, debt). | | React / react-dom | 16.0 | 18 | ✅ done — 18.3.1 + createRoot. The peripheral react-* libs that only worked on 18 via legacy context are now all modernized (see rows below) **except react-leaflet** (deferred). What still blocks React 19: react-leaflet 1.8, plus our own `defaultProps` on function components and one `findDOMNode` (gadicc:blaze-react-component in Reconnect) — cosmetic, tracked. |
| Server async/await | Fibers | `*Async` APIs | ✅ done — REST, publications, methods, startup and migrations all on `*Async`. | | Server async/await | Fibers | `*Async` APIs | ✅ done — REST, publications, methods, startup and migrations all on `*Async`. |
| bcrypt | 1.0.3 (broken binding) | 5.x | ✅ done — 1.0.3 didn't load on Node 22 (accounts-password silently fell back to pure JS) and wouldn't compile in the Docker build; 5.1.1 ships Node-22 prebuilds. | | bcrypt | 1.0.3 (broken binding) | 5.x | ✅ done — 1.0.3 didn't load on Node 22 (accounts-password silently fell back to pure JS) and wouldn't compile in the Docker build; 5.1.1 ships Node-22 prebuilds. |
| raven / flowkey:raven | 2.4 | @sentry/node + @sentry/browser 8.x | ✅ done — `flowkey:raven` (Sentry legacy SDK, dead on 3.x, spammed the boot log with 502s against the dead sentry.comunes.org) replaced by the modern SDKs behind the same `ravenLogger.log()` facade (6 call sites unchanged). Backend: **GlitchTip** self-hosted on `aaron` (Sentry-compatible DSN/API; Sentry proper needs 16 GB RAM, didn't fit), deployed via the Comunes ansible (`glitchtip.yml`, org "comunes" / project "tcef-web"), fronted at `https://sentry.comunes.org` (nginx on `assange``aaron:8000`). DSN set in `settings-development.json`; end-to-end verified (a test exception sent from the dev server showed up in GlitchTip within seconds). | | raven / flowkey:raven | 2.4 | @sentry/node + @sentry/browser 8.x | ✅ done — `flowkey:raven` (Sentry legacy SDK, dead on 3.x, spammed the boot log with 502s against the dead sentry.comunes.org) replaced by the modern SDKs behind the same `ravenLogger.log()` facade (6 call sites unchanged). Backend: **GlitchTip** self-hosted on `aaron` (Sentry-compatible DSN/API; Sentry proper needs 16 GB RAM, didn't fit), deployed via the Comunes ansible (`glitchtip.yml`, org "comunes" / project "tcef-web"), fronted at `https://sentry.comunes.org` (nginx on `assange``aaron:8000`). DSN set in `settings-development.json`; end-to-end verified (a test exception sent from the dev server showed up in GlitchTip within seconds). |
@ -310,7 +317,7 @@ MONGO_CONTAINER=tcef-mongo7 MONGO_SHELL=mongosh MONGO_PORT=27019 ./smoke/smoke.s
| react-meteor-data | 0.2.16 | 3.0.6 | ✅ done — 0.2.16 (React-15/16-era) looped `withTracker` on fire-detail pages under React 18 (never-ready → blank). `meteor add react-meteor-data@3.0.6`; no call-site changes (HOC API kept). Also dropped `tmeasday:check-npm-versions` (the constraint pinning 0.2.16). See section above. | | react-meteor-data | 0.2.16 | 3.0.6 | ✅ done — 0.2.16 (React-15/16-era) looped `withTracker` on fire-detail pages under React 18 (never-ready → blank). `meteor add react-meteor-data@3.0.6`; no call-site changes (HOC API kept). Also dropped `tmeasday:check-npm-versions` (the constraint pinning 0.2.16). See section above. |
| i18next | 10.5 | 23.16 | ✅ done — with react-i18next 14. `whitelist``supportedLngs`, added `compatibilityJSON: 'v3'` (our locale JSON uses natural-language keys + v3 `_plural` layout, not the v4 `_one`/`_other` suffixes), custom separators `ß`/`ð`/`đ` kept. `sendMissing``saveMissing`, missingKeyHandler signature is `(lngs, ns, key, fallbackValue)` now (array first). See react-i18next row. | | i18next | 10.5 | 23.16 | ✅ done — with react-i18next 14. `whitelist``supportedLngs`, added `compatibilityJSON: 'v3'` (our locale JSON uses natural-language keys + v3 `_plural` layout, not the v4 `_one`/`_other` suffixes), custom separators `ß`/`ð`/`đ` kept. `sendMissing``saveMissing`, missingKeyHandler signature is `(lngs, ns, key, fallbackValue)` now (array first). See react-i18next row. |
| react-i18next | 7.4 | 14.1 | ✅ done — 48 `translate([], {wait:true})`/`translate()` HOCs → `withTranslation()`; `react.wait:true``react.useSuspense:false`. `<Trans>` unchanged (locale JSON already stores the indexed-tag format `<1><0>{{x}}</0></1>`). ReSendEmail: removed `<Interpolate>` (deleted in v10) → `<Trans i18nKey values={{email}}/>`, dropped the removed bare `t` export. This is what silenced the per-component `Translate`/`I18n` legacy-context console spam. Backends: xhr→`i18next-http-backend` (client), sync-fs→`i18next-fs-backend` (server); `i18next-localstorage-cache` dropped (was `enabled:false`); languagedetector 2→8. Browser-verified: es/en switch, `<Trans>` interpolation (`{{countTotal}}`+`<strong>`) renders on /fires. | | react-i18next | 7.4 | 14.1 | ✅ done — 48 `translate([], {wait:true})`/`translate()` HOCs → `withTranslation()`; `react.wait:true``react.useSuspense:false`. `<Trans>` unchanged (locale JSON already stores the indexed-tag format `<1><0>{{x}}</0></1>`). ReSendEmail: removed `<Interpolate>` (deleted in v10) → `<Trans i18nKey values={{email}}/>`, dropped the removed bare `t` export. This is what silenced the per-component `Translate`/`I18n` legacy-context console spam. Backends: xhr→`i18next-http-backend` (client), sync-fs→`i18next-fs-backend` (server); `i18next-localstorage-cache` dropped (was `enabled:false`); languagedetector 2→8. Browser-verified: es/en switch, `<Trans>` interpolation (`{{countTotal}}`+`<strong>`) renders on /fires. |
| Leaflet | 1.3.1 | current | debt — pin; not on the critical path | | react-leaflet + leaflet | 1.8 / 1.3.1 | 4.x / 1.9 | ⏸️ **deferred as debt** (the one lib not modernized this pass). react-leaflet v4 is a ground-up hooks rewrite of the app's core feature (the fire map), and the migration is deeply entangled: (a) **4 unmaintained v1-only plugins with no v4 equivalent**`react-leaflet-control` (custom map buttons, 3 maps), `react-leaflet-fullscreen`, `react-leaflet-google` (`GoogleLayer` base layers in DefMapLayers), `leaflet-sleep` (`sleep`/`wakeTime`… props on `<Map>`) — each needs a bespoke `createControlComponent`/`createLayerComponent`/googlemutant reimplementation; (b) the **controlled-viewport** pattern (`onViewportChanged` + `state.center/zoom` in FiresMap/SelectionMap) is gone in v4 (`MapContainer` center/zoom are initial-only; you drive it via a `useMap()` child); (c) `.leafletElement` refs in 6 files/13 sites (FiresMap, SelectionMap, SubscriptionsMap, Fires, SubsUnion) — v4 hands you the `L.Map`/layer directly with different timing; (d) `Leaflet.control.graphicScale().addTo(map)` + `subsUnion` reach into the raw map via the ref. **v1.8 works on React 18** (verified: all maps render), so this only blocks the eventual React 19 jump. Do it as its own focused project with heavy in-browser verification (drag markers, viewport-driven fire reload, fitBounds, layer switch, fullscreen, sleep, custom controls). Stays pinned at 1.8 until then. |
| arkham:comments-ui | 1.4.x | — | ✅ replaced with in-repo React feature | | arkham:comments-ui | 1.4.x | — | ✅ replaced with in-repo React feature |
| nimble:restivus | Atmosphere | vendored | ✅ local precompiled package, accounts-password 2.x | | nimble:restivus | Atmosphere | vendored | ✅ local precompiled package, accounts-password 2.x |
| maximum:server-transform, meteorhacks:zones, less, markdown, test stack | — | — | ✅ removed (dead/unused) | | maximum:server-transform, meteorhacks:zones, less, markdown, test stack | — | — | ✅ removed (dead/unused) |