2.1 — Filosofia: Compilador vs Runtime

A diferença fundamental que define tudo o mais.

Objetivos da Aula

  • Entender a diferença entre abordagem de compilador e runtime
  • Compreender o que significa “Svelte desaparece”
  • Analisar o impacto no tamanho do bundle e performance

A Grande Divisão

A diferença mais fundamental entre Svelte e React está na quando o trabalho é feito:

Quando o Trabalho Acontece

React (Runtime)

Seu Codigo
JSX
Bundle
React + seu app
Runtime
executa no navegador
DOM
atualizado

Trabalho:

Build Navegador (runtime pesado)

Svelte (Compilador)

Seu Codigo
.svelte
Compilador
Svelte (build)
JS otimizado
zero runtime
DOM
atualizado

Trabalho:

Build (compilacao pesada) Navegador (leve)

React: O Caminho do Runtime

Como React Funciona

  1. Você escreve JSX (uma extensão de sintaxe)
  2. Babel transforma JSX em chamadas React.createElement()
  3. O React Runtime (biblioteca) é enviado ao navegador
  4. O runtime gerencia o Virtual DOM
  5. A cada mudança de estado, o runtime:
    • Re-executa a função do componente
    • Gera nova árvore Virtual DOM
    • Compara com a anterior (diffing)
    • Aplica mudanças mínimas ao DOM real
// O que você escreve
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c + 1)}>
    {count}
  </button>
}

// O que vai para o navegador (simplificado)
function Counter() {
  const [count, setCount] = React.useState(0);
  return React.createElement(
    "button",
    { onClick: () => setCount(c => c + 1) },
    count
  );
}

// + 40KB+ do React Runtime
// + 10KB+ do ReactDOM
// = 50KB+ antes do seu código

O Custo do Runtime

// React Runtime precisa:
// 1. Sistema de Virtual DOM
// 2. Algoritmo de Reconciliação (diffing)
// 3. Sistema de Hooks
// 4. Scheduler (Concurrent Mode)
// 5. Sistema de Eventos Sintéticos

// Tudo isso: ~50KB+ gzipped

Svelte: O Caminho do Compilador

Como Svelte Funciona

  1. Você escreve código .svelte
  2. O Compilador Svelte analisa seu código no build
  3. Gera JavaScript vanilla otimizado
  4. Nenhum runtime é enviado ao navegador
  5. O código gerado manipula o DOM diretamente
<!-- O que você escreve -->
<script>
  let count = 0
</script>

<button on:click={() => count++}>
  {count}
</button>
// O que o compilador gera (simplificado)
function create_fragment(ctx) {
  let button;
  let t;

  return {
    c() {
      button = element("button");
      t = text(ctx[0]); // count
    },
    m(target, anchor) {
      insert(target, button, anchor);
      append(button, t);
      // Event listener direto, sem sistema de eventos sintéticos
      button.addEventListener("click", ctx[1]);
    },
    p(ctx, [dirty]) {
      // Atualização cirúrgica - só muda o texto se count mudou
      if (dirty & 1) set_data(t, ctx[0]);
    },
    d(detaching) {
      if (detaching) detach(button);
      button.removeEventListener("click", ctx[1]);
    }
  };
}

// Helpers mínimos: ~2KB
// Seu componente: ~0.5KB
// Total: ~2.5KB

O que “Svelte Desaparece” Significa

Svelte Desaparece

Tempo de Build:

Seu codigo
.svelte
Compilador Svelte
faz todo trabalho
JS puro
output

Runtime (navegador):

Apenas o JS gerado executa

Nao existe "Svelte" rodando

So JavaScript vanilla manipulando DOM

"Svelte desaparece" = O framework nao existe em runtime


Comparação Visual: Virtual DOM vs DOM Direto

React (Virtual DOM)

Estado muda: count = 1 → count = 2

1

Re-executa toda a funcao do componente

2

Cria NOVA arvore Virtual DOM

{ type: 'button', props: { children: 2 } }

3

COMPARA com arvore anterior (diffing)

{ type: 'button', props: { children: 1 } }

→ Encontra diferenca: children mudou

4

Aplica mudanca minima ao DOM real

textNode.textContent = 2

Trabalho: Re-render + Diff + Patch = 3 passos

Svelte (DOM Direto)

Estado muda: count = 1 → count = 2

1

Compilador JA SABE que count afeta o textNode

(analise estatica em tempo de build)

2

Codigo gerado atualiza DIRETAMENTE

if (dirty & 1) textNode.data = count

Trabalho: Update direto = 1 passo

Nao existe:

Re-execucao de funcao

Criacao de objetos Virtual DOM

Algoritmo de diff


O Poder da Análise Estática

O compilador Svelte faz análise estática do seu código:

<script>
  let name = 'mundo'        // ← Variável reativa
  let count = 0             // ← Variável reativa
  const PI = 3.14159        // ← Constante (não precisa rastrear)

  function increment() {
    count += 1              // ← Compilador sabe que isso muda `count`
  }
</script>

<h1>Olá, {name}!</h1>        <!-- Depende de `name` -->
<p>Contagem: {count}</p>     <!-- Depende de `count` -->
<p>Pi: {PI}</p>              <!-- Depende de `PI` (constante) -->
<button on:click={increment}>+</button>

O compilador sabe em tempo de build:

  • Quais variáveis são reativas
  • Quais partes do DOM dependem de cada variável
  • Quais atualizações são necessárias quando algo muda
// Código gerado (simplificado)
p(ctx, [dirty]) {
  // `dirty` é um bitmask indicando O QUE mudou

  // Se `name` mudou (bit 0)
  if (dirty & 1) set_data(t0, ctx[0]); // Atualiza "Olá, {name}!"

  // Se `count` mudou (bit 1)
  if (dirty & 2) set_data(t1, ctx[1]); // Atualiza "Contagem: {count}"

  // PI nunca muda, então não há código para atualizá-lo!
}

Implicações Práticas

Tamanho do Bundle

Aplicacao "Hello World" com contador

React

react.production.min.js~2.5 KB
react-dom.production.min.js~40 KB
seu codigo~0.5 KB
TOTAL~43 KB

Svelte

runtime helpers~2 KB
seu codigo compilado~1.5 KB
TOTAL~3.5 KB

Svelte e ~12x menor!

Escalabilidade do Bundle

Conforme sua aplicação cresce:

React:
  Base: ~43 KB (runtime fixo)
  + Componentes: cresce linearmente
  + Bibliotecas (Redux, etc): +30-50 KB

Svelte:
  Base: ~2 KB (helpers mínimos)
  + Componentes: cresce linearmente (mas código mais eficiente)
  + Stores nativos: 0 KB adicional

Em apps grandes, a diferença diminui proporcionalmente,
mas Svelte sempre começa menor.

Performance de Atualização

// Benchmark: Atualizar 1000 itens em uma lista

// React (Virtual DOM)
// 1. Cria 1000 objetos Virtual DOM novos
// 2. Compara com 1000 objetos anteriores
// 3. Identifica mudanças
// 4. Aplica ao DOM
// Tempo: ~15-25ms

// Svelte (DOM Direto)
// 1. Atualiza diretamente os elementos que mudaram
// Tempo: ~3-8ms

Quando Cada Abordagem Brilha

React (Runtime) é Melhor Quando:

  • 🏢 Ecossistema é prioridade — milhares de bibliotecas
  • 👥 Time grande — mais fácil encontrar desenvolvedores
  • 🔄 Mudanças dinâmicas intensas — Virtual DOM amortiza custo
  • 🧪 Padrões estabelecidos — arquiteturas bem documentadas

Svelte (Compilador) é Melhor Quando:

  • Performance é crítica — apps que precisam ser rápidos
  • 📱 Mobile/Low-end devices — menos JS = mais rápido
  • 📦 Bundle size importa — landing pages, widgets, embeds
  • 🎯 DX é prioridade — menos boilerplate, código mais limpo
  • 🆕 Projeto novo — sem bagagem de código legado

Exemplo Comparativo Completo

React

// Counter.jsx
import { useState, useCallback, useMemo } from 'react'
import './Counter.css'

export function Counter({ initialValue = 0, step = 1 }) {
  const [count, setCount] = useState(initialValue)

  const increment = useCallback(() => {
    setCount(c => c + step)
  }, [step])

  const decrement = useCallback(() => {
    setCount(c => c - step)
  }, [step])

  const isEven = useMemo(() => count % 2 === 0, [count])

  return (
    <div className="counter">
      <span className={isEven ? 'even' : 'odd'}>
        {count}
      </span>
      <button onClick={decrement}>-{step}</button>
      <button onClick={increment}>+{step}</button>
    </div>
  )
}

// Linhas: 24
// Imports: 3 hooks
// Bundle: +43KB base + código

Svelte

<!-- Counter.svelte -->
<script>
  export let initialValue = 0
  export let step = 1

  let count = initialValue

  function increment() {
    count += step
  }

  function decrement() {
    count -= step
  }

  $: isEven = count % 2 === 0
</script>

<div class="counter">
  <span class:even={isEven} class:odd={!isEven}>
    {count}
  </span>
  <button on:click={decrement}>-{step}</button>
  <button on:click={increment}>+{step}</button>
</div>

<style>
  .counter { /* estilos */ }
  .even { color: green; }
  .odd { color: blue; }
</style>

<!-- Linhas: 28 (incluindo CSS!)
     Imports: 0
     Bundle: ~3KB base + código -->

✅ Desafio da Aula

Objetivo

Analisar o output do compilador Svelte para entender o que ele gera.

Instruções

  1. Vá para svelte.dev/repl
  2. Escreva um componente simples com uma variável e um botão
  3. Clique na aba “JS output” para ver o código gerado
  4. Identifique:
    • Onde o elemento é criado
    • Onde o evento é adicionado
    • Onde a atualização acontece

Spec de Verificação

  • Você consegue identificar a função create_fragment
  • Você encontrou onde o addEventListener é chamado
  • Você encontrou a função de update (p)
  • Você entende que não há Virtual DOM no código gerado

Reflexão

Responda mentalmente:

  1. O código gerado usa document.createElement ou React.createElement?
  2. Existe algum “diff” sendo feito?
  3. Onde está o “Svelte” no código gerado?

📚 Recursos Adicionais


Próxima aula: 2.2 — Reatividade: atribuição vs hooks