Guia: Injeção Dinâmica de Recursos (Deep Dive)
A injeção dinâmica é o pilar que permite que nosso monorepo escale para dezenas de domínios sem degradar a performance do navegador ou a experiência do desenvolvedor. Este guia detalha o funcionamento interno dessa mecânica.
O Problema da Store Estática
Em aplicações Redux tradicionais, todos os reducers são combinados em um rootReducer no momento em que a aplicação inicia.
// ❌ Abordagem Estática (Não usamos)
const store = configureStore({
reducer: {
auth: authReducer,
consultation: consultationReducer,
chat: chatReducer,
scheduling: schedulingReducer,
// ... + 50 domínios
}
});Consequências:
- Bundle Size: O JavaScript de todos os domínios é baixado no carregamento inicial.
- Memória: Reducers e Sagas de módulos que o usuário nunca acessará ficam ocupando espaço.
- Acoplamento: Todos os domínios precisam ser conhecidos pela App central.
Nossa Solução: Store Manager
Utilizamos um StoreManager customizado em packages/core/store que permite adicionar reducers em runtime.
1. Como funciona o Reducer Injector
Quando um domínio é montado, ele dispara o registro do seu reducer.
// core/store-injector/reducer-injector.ts
export function injectReducer(key: string, reducer: Reducer) {
if (store.asyncReducers[key]) return; // Evita duplicidade
store.asyncReducers[key] = reducer;
store.replaceReducer(createReducer(store.asyncReducers));
}2. Como funciona o Saga Injector
Diferente dos reducers, sagas são processos em execução. O injetor garante que o saga comece a rodar e gerencia o seu ciclo de vida.
// core/store-injector/saga-injector.ts
export function injectSaga(key: string, saga: Saga) {
const hasSaga = store.injectedSagas.has(key);
if (!hasSaga) {
const task = store.runSaga(saga);
store.injectedSagas.set(key, task);
}
}Uso Prático nos Domínios
Os desenvolvedores devem usar os hooks useInjectReducer e useInjectSaga no componente de entrada do domínio.
Exemplo: Domínio de Telemetria
import { useInjectReducer, useInjectSaga } from 'core/store-injector';
import { telemetryReducer, telemetrySaga } from './store';
export const TelemetryPage = () => {
// 1. Injeta os recursos técnicos
useInjectReducer({ key: 'telemetry', reducer: telemetryReducer });
useInjectSaga({ key: 'telemetry', saga: telemetrySaga });
// 2. Renderiza a interface
return <TelemetryDashboard />;
};Boas Práticas e Cuidados
- Nomes Únicos: A
keyde injeção deve ser única no ecossistema. Use o nome do domínio (ex:consultation,chat). - Limpeza de Estado (Eject): Por padrão, mantemos o estado do reducer mesmo após o componente desmontar (para cache). Se o domínio for muito pesado, o
useInjectReducerpode ser configurado para limpar o estado nounmount. - Ordem de Injeção: Sempre injete os recursos no componente que define a rota (Page), garantindo que sub-componentes já tenham acesso ao estado.
- Sagas de Escuta Global: Sagas que precisam ouvir eventos de domínio (
Domain Events) devem ser injetados preferencialmente no nível da App ou em um domínio que esteja sempre ativo, caso contrário, eles só ouvirão eventos enquanto a página do domínio estiver aberta.
Verificação Técnica
Para verificar se a injeção funcionou:
- Abra o Redux DevTools.
- Navegue para a rota do domínio.
- Note que uma nova chave (ex:
telemetry) apareceu na árvore de estado e as ações do saga começaram a ser logadas.