Un'istantanea di sessione per la scheda, non una per istanza gancio

Performancekamo-internal
Spegnimento
26 agosto 2026 alle ore 05:40 UTC
Autore
kamo
Impegno
2241a5c

useUserInfo ha tenuto la sua sessione in tre celle useState. Ha 187 siti di chiamata e circa 27 di sono montati per l'intera sessione — il nav, ogni fornitore di shell, il lanciopad. The RICHIESTA era già a carbone, quindi c'era solo una chiamata /api/user-info, ma quando risolto tutte le 27 istanze chiamate il proprio setUserInfo con gli stessi dati. Ventisette aggiornamenti indipendenti React che trasportano lo stato identico, su ogni scheda messa a fuoco e ogni cinque minuti Tick. Lo stato si sposta in un negozio di moduli dietro l'usoSyncExternalStore, quindi un aggiornamento è una scrittura e un passaggio di rendering in batch. Il negozio è app/lib/userInfoStore.ts piuttosto che un modulo hook-local per una ragione specifica: nulla in questo repo può catturare una regressione dei diritti. Non c'è @testing-library, nessun test monta un componente, e app/hooks/** non è nell'elenco incluso di vitest — un test posto accanto L'amo passerebbe senza correre. app/lib/** è inclusa, così le regole che i diritti di gate attraverso il prodotto ora hanno 25 test che coprono ogni percorso di scrittura. Tre proprietà sono portanti di carico e ciascuno è bloccato da un test: `loading` inizia TRUE ed è un fermo a senso unico. Le guardie dei diritti si introducono a una DENY, non a a wait, and checkRight si apre con `if (!userInfo) ritorno falso` — quindi un negozio di report caricamento:false prima che i dati arrivino rende "nessun permesso" a un membro che detiene il diritto, e accende i venti `useEffect(..., [loading])` reindirizza che leggono i diritti sul primo rendering non carica. Niente si schianta e nessun test fallisce. Allo stesso modo, non deve mai tornare al vero, o ogni guardia nell'app lampeggia il suo stato di carico ogni cinque minuti. Le scritture sono solo browser per costruzione. Sul server un processo serve ogni concorrente richiesta, quindi una variabile di modulo che detiene i diritti di un membro è una condivisa con l'altra rendering del membro. pubblicare() rifiuta di scrivere senza una finestra e ottenereServerSnapshot restituisce un congelato costante invece di leggere l'istantanea mutabile. Questa costante è anche obbligatoria: shell autenticata è server-rendered e questo gancio viene raggiunto durante il passaggio del server dal albero client del layout radice, dove React 19 getta piuttosto che cadere indietro, senza limite sopra AuthedChrome per catturarlo. L'istantanea è tenuta, mai ricostruita. loadUserInfoShared restituisce un oggetto appena trattato ogni il tempo, che è proprio il motivo per cui tutti i 27 istanze re-rendered; un getSnapshot che costruito uno avrebbe non solo re-render ma lanciare. I carichi equivalenti non pubblicano più affatto, quindi i consumatori keying memos off userInfo identità — ImpostazioniAppPinsContext nav gate soprattutto — stop ricomputare ogni cinque minuti per un carico utile che non ha cambiato. Tre decisioni che vale la pena di nominare, perché ciascuno aveva un'alternativa defensibile: La navigazione /logout è ora gated là essendo un abbonato. Il vecchio èMountedRef guardia seduto sopra l'interruttore, non su un setState, quindi ha saltato il reindirizzamento troppo — un'istanza che non montato metà volo non ha navigato. Cancellare il ref outright, che è la mossa abituale quando si adotta un modulo store, avrebbe silenziosamente promosso che reindirizzare da condizionale a incondizionato. Solo il primo carico è in primo piano; in seguito monta rinfrescare in background. I diritti rimangono freschi sulla navigazione come prima, ma un errore transitorio su un supporto in ritardo non può più essere pubblicato tutti i 27 consumatori quando in precedenza ha svuotato solo l'istanza che ha colpito. I sette caricatori esterniUserInfoShared deliberatamente non pubblicano. loro sparano websocket riconnettersi a tempi arbitrari, e guidare il prodotto gating da una superficie di trigger nessuno sta guardando è peggiore della stalaness delimitata di non farlo — essi leggono scalar identità che non può cambiare all'interno di una sessione. Gli accessori sono lasciati come semplici frecce di proposito. Stabilizzarli è l'istinto naturale qui e rompere silenziosamente nove siti di chiamata — utilizzareHrOverview, utilizzareSubscriptionPermissioni, PlatformRightsContext e altri sei — che dipendono dall'identità instabile di oggi per rimanere fresco, computer una volta contro una snapshot nulla invece. L'ingresso /logout consentlist nel check-client-navigation. mjs segue la linea per cui esiste. Verificato: tsc clean, tutte le 10 guardie passano, 3286 prove verdi, compilazioni di costruzione di produzione, e la server standalone rende ancora la shell autenticata — 200, 16,238 byte di DOM attraverso 153 elementi, due intestazioni, dieci pulsanti, My Businesses / Il mio profilo / Log out. Vuole un essere umano cliccare attraverso i diritti-gated nav, un membro dei diritti limitati, e una sessione di scadenza prima di esso navi.

Tutte le modifiche

Come quello che vedi la spedizione?

Ognuno di questi aggiornamenti atterra automaticamente nello spazio di lavoro. Inizia gratis e guardalo crescere settimana dopo settimana.

Inizia gratis per sempreVisualizza il prezzo