Migrering av klientdelen uten nedetid
Omskriver klientdelen. 170 lokasjoner bruker den fortsatt. Ingen nedetid.
En CRA-til-Next.js-migrering i et produksjonssystem, med et V2-skall, iframe-bro, delt autentisering, synkronisert ruting og trinnvis utrulling.
5 min lesetidAv Abdullah Raheel
Produktet kunne ikke stoppe
CRA V1 betjente fortsatt 170 lokasjoner og rundt 765 samtidige brukere. Vi kunne ikke stoppe funksjonsutviklingen, bygge en erstatning isolert og flytte alle kundene samtidig. Migreringen måtte skje inne i produktet som var i drift.
Vi brukte Strangler Fig-mønsteret: legg det nye systemet rundt det gamle, flytt ett produksjonsansvar om gangen, og slett kompatibilitetslaget når ingenting avhenger av det.
Bruk strangler-mønsteret, ikke en ny total lansering
Next.js V2 ble applikasjonsskallet. Det eide Navbar, Topbar, autentiseringen og den felles siderammen. Ruter som ennå ikke var migrert, fortsatte i én CRA-iframe. Kundene så dermed ett produkt mens to kjøretider for klientdelen var aktive.
Iframe-en lastet alltid en stabil basis-URL for kontrollpanelet. Den forble montert når den overordnede ruten endret seg. Ny montering ville ha nullstilt den eldre tilstanden og gjentatt autentiseringen. V2 sendte bare den første ruten fra iframe-ens onLoad-callback, etter at V1 hadde installert meldingslytteren. Senere endringer ble bare sendt når den tilordnede ruten faktisk endret seg.
iframe.contentWindow?.postMessage(
{
action: 'NAVIGATE',
route: iframeRoute,
location_id: locationId,
migratedLocationIds: [...MIGRATED_LOCATION_IDS]
},
dashboardUrl
)Få to klientdeler til å oppføre seg som én
Vi definerte begge meldingsretningene uttrykkelig. V2 sendte navigasjon, SSO-tokener, brukerdata og lokasjonsdata. V1 sendte ruteendringer, forespørsler om brukerdata, forespørsler om tokenfornyelse og Click2Call-handlinger tilbake.
Hver mottaker avviste ukjente opprinnelser, og hver avsender brukte den konfigurerte applikasjonsopprinnelsen som mål i stedet for et jokertegn. Kontroll av opprinnelse var den første grensen, ikke full validering av nyttelasten. Meldinger som inneholdt tokener, måtte også ha kjente meldingstyper og validerte felt.
if (event.origin !== dashboardUrl) return
if (event.data?.source !== 'dispo-iframe') return
if (event.data?.type !== 'ROUTE_CHANGE') return
const route = mapV1RouteToV2(event.data.route)
if (route) router.replace(route)Én pålogging måtte autentisere begge applikasjonene
Brukeren autentiserte seg én gang i V2. Da V1 ble lastet, ba den om gjeldende brukerkontekst. V2 returnerte SSO-tokenet samt bruker- og lokasjonsdata. V1 lagret tokenet for den eksisterende API-klienten og ba om et nytt gjennom samme bro etter utløp.
En proaktiv autentiserings-hook ble innført mens vi undersøkte en kappløpstilstand ved oppstart av iframe-en. Den forsøkte å sende autentiseringen før V1 ba om den, men la til enda et tidsavhengig forløp og ble for ivrig. En senere endring fjernet denne hooken og beholdt reaktiv autentisering med forespørsel og svar. Dermed hadde tidspunktet for tokenet én tydelig eier.
La adressefeltet og nettleserhistorikken vise riktig rute
V2 tilordnet rutene sine til V1-baner som /dashboard, /buyer-genie, /deals og /my-buyers. Den motsatte tilordningen håndterte både nøyaktige ruter og nestede prefikser. Når navigasjonen startet i V1, brukte V2 router.replace. Adressefeltet og aktiv navigasjon ble da oppdatert uten at én brukerhandling opprettet enda en oppføring i historikken.
Dermed hang oppdatering, dyplenker og nettleserens frem- og tilbakenavigasjon sammen. Tilbake i nettleseren endret den overordnede ruten, den overordnede applikasjonen sendte den tilordnede underruten, og den monterte iframe-en navigerte uten å laste skallet på nytt.
Flytt kunder og funksjoner i kontrollerte etapper
MIGRATED_LOCATION_IDS var bryteren for utrullingen. Vi startet med interne lokasjoner og staginglokasjoner og utvidet deretter til åtte kundelokasjoner. Alle utenfor listen fortsatte på den eksisterende V1-banen.
- Bygd direkte i V2: Navbar, Topbar, Settings, Investor Intake, SSO og Twilio Dialer.
- Fortsatt i V1 ved det dokumenterte midtpunktet: Home, Genius Mode, Deals og Buyers.
- Migreringsenhet: én funksjon og utvalgte kundelokasjoner, ikke én separat lansering.
Erstatningen var usynlig under utrullingen
Kompatibilitetslaget ble til slutt fjernet i stedet for å bli permanent arkitektur. Overgangen slettet iframe-systemet og de eldre, genererte API-klientene, flyttet gjenværende klienter inn under V2, la til den innebygde påloggingsbanen og ryddet deretter opp i ruter, tester, delt oppringingskode, autentiseringsvakter og komponentstruktur.
I en periode vedlikeholdt vi to rutere, to sesjonsmodeller, hendelser mellom vinduer, rutetilordninger og kappløpstilstander ved oppstart. Kostnaden var bare akseptabel fordi hver migrerte rute førte oss nærmere å kunne slette broen.

