R
Interview Deckreact · next.js · senior/staff
0·0·122
Arquitetura

System Design para Frontend

Como estruturar uma entrevista de system design focada em frontend: componentes, estado, performance.

System design frontend avalia como você pensa em escala: componentes reutilizáveis, gerenciamento de estado global, comunicação com APIs, caching, performance, acessibilidade e deploy. Diferente do backend, o foco é em UX e responsividade. As perguntas típicas: "Como você construiria o Feed do Twitter?", "Projete um autocomplete", "Como você faria uma grid de imagens infinita?".

Problema
Candidatos focam demais em código e esquecem de discutir trade-offs, escalabilidade e decisões de arquitetura. Ou o oposto: ficam muito abstratos sem demonstrar conhecimento técnico concreto.
Solução
Framework para responder: 1) Clarificar requisitos (funcional e não-funcional), 2) Estimativas (usuários, requests, tamanho de dados), 3) High-level design (componentes principais), 4) Deep dive (o que o entrevistador pedir), 5) Trade-offs e melhorias.
Tip
Em frontend system design, sempre mencione: renderização (CSR/SSR/SSG), estado (local vs global vs server state), performance (lazy loading, code splitting, caching), acessibilidade e testes. Demonstra que você pensa além do código feliz.
// Autocomplete com debounce + cache + cancelamento
function useAutocomplete(query: string) {
  return useQuery({
    queryKey: ['autocomplete', query],
    queryFn: async ({ signal }) => {
      const res = await fetch(`/api/search?q=${query}`, { signal })
      return res.json()
    },
    enabled: query.length > 1,
    staleTime: 5 * 60 * 1000, // cache por 5min
  })
}

// Infinite scroll com IntersectionObserver
function useInfiniteScroll(callback: () => void) {
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) callback() },
      { threshold: 0.1 }
    )
    if (ref.current) observer.observe(ref.current)
    return () => observer.disconnect()
  }, [callback])

  return ref
}

// Uso com React Query infinite
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
  queryKey: ['images'],
  queryFn: ({ pageParam = 1 }) => fetchImages(pageParam),
  getNextPageParam: (last) => last.nextPage,
})
const loaderRef = useInfiniteScroll(() => {
  if (hasNextPage) fetchNextPage()
})
Q.Como projetaria um autocomplete escalável?
A.Debounce de 200-300ms para reduzir requests. Cache de resultados anteriores (Map ou React Query cache). Cancelamento de request anterior com AbortController. Virtualização da lista se muitos resultados. Acessibilidade: aria-combobox, aria-listbox, navegação com setas. Highlight do match no texto.
Q.Como projetaria um infinite scroll de imagens?
A.IntersectionObserver para detectar quando o usuário chega ao fim. React Query com useInfiniteQuery para gerenciar paginação e cache. Virtualização (react-virtual ou react-window) para não manter todos os itens no DOM. Skeleton loading por placeholder. Otimização de imagens: lazy loading nativo, WebP, tamanhos responsivos.
Q.Qual a diferença entre CSR, SSR e SSG?
A.CSR: renderiza no browser, TTI alto, ruim para SEO. SSR: renderiza no servidor por request, TTFB maior mas TTI menor, bom para SEO e dados dinâmicos. SSG: renderiza no build, TTFB mínimo, ótimo para conteúdo estático ou com revalidação (ISR). Escolha: SEO crítico + dados dinâmicos = SSR; SEO + dados estáticos = SSG; app autenticado sem SEO = CSR.
78/122← →