Skip to content

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.

typescript
// ❌ Abordagem Estática (Não usamos)
const store = configureStore({
  reducer: {
    auth: authReducer,
    consultation: consultationReducer,
    chat: chatReducer,
    scheduling: schedulingReducer,
    // ... + 50 domínios
  }
});

Consequências:

  1. Bundle Size: O JavaScript de todos os domínios é baixado no carregamento inicial.
  2. Memória: Reducers e Sagas de módulos que o usuário nunca acessará ficam ocupando espaço.
  3. 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.

typescript
// 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.

typescript
// 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

tsx
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

  1. Nomes Únicos: A key de injeção deve ser única no ecossistema. Use o nome do domínio (ex: consultation, chat).
  2. 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 useInjectReducer pode ser configurado para limpar o estado no unmount.
  3. Ordem de Injeção: Sempre injete os recursos no componente que define a rota (Page), garantindo que sub-componentes já tenham acesso ao estado.
  4. 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.