Svelte: o que é, como funciona e diferenças com o React JS

Svelte: o que é, como funciona e diferenças com o React JS

Frameworks JavaScript

Inegavelmente, o React é a ferramenta que atualmente domina o mercado front-end, sendo a mais utilizada de acordo com a pesquisa de 2020 do State of JS, seguida de seus concorrentes Angular e Vue.js. Essa demanda também é notável quando pesquisamos por vagas em plataformas de empregos.

Porém, uma nova ferramenta vem ganhando força nos últimos anos e superou todos os outros frameworks nessa mesma pesquisa no quesito satisfação: o Svelte.

Banner promocional da Alura, com um design futurista em tons de azul, apresentando o texto

O que é Svelte?

O Svelte é um compilador utilizado para construir interfaces web, assim como React, Angular e Vue.js. Ele foi criado em 2016 por Rich Harris, e vem com a proposta de ser mais performático, fácil de aprender e utilizar, possuindo uma alta curva de aprendizagem, além da sintaxe simples e intuitiva.

Ele em si é muito leve, possuindo 4.4kB, ou 1.6 kB comprimido, custando muito menos para os navegadores baixarem os arquivos. Para comparação, os pacotes react e react-dom, juntos, somam 126kB, ou 42.2kB comprimidos.

Como funciona o Svelte e um compilador no Front-End?

O compilador do Svelte lê o código que escrevemos e o compila para JavaScript puro, sem utilizar Virtual DOM. O código gerado é extremamente performático em relação aos seus concorrentes.

Você também pode ver o processo de compilação na prática, utilizando o REPL, uma ferramenta criada pelo Svelte, onde podemos testar nossos códigos online e ver os arquivos JS gerados.

Dica: utilize o REPL para testar os exemplos deste artigo!

Como trabalhar com o Svelte?

Agora que você entende como funciona o Svelte e o quão performático ele é, vamos compará-lo com o React, com alguns exemplos de código!

Svelte vs React: Comparação de códigos

Estrutura de um componente

Vamos considerar o seguinte código React:

import './App.css';
import { useState } from 'react';

function App() {
  const [nome, setNome] = useState('World');

  return (
    <div className="App">
      <h1>Hello {nome}!</h1>
    </div>
  );
}

export default App;

Com o Svelte, o mesmo código acima ficaria assim:

<script>
    let nome = 'World';
</script>

<main>
    <h1>Hello {nome}!</h1>
</main>

<style>
    main {
        /* estilos de main */
    }

    h1 {
        /* estilos de h1 */
    }
</style>

O Svelte utiliza a estrutura Single File Component (Componente de Arquivo Único), onde deixamos HTML, CSS e JS num mesmo arquivo com extensão .svelte. Vemos no exemplo acima que o JS fica dentro da tag <script>, o CSS dentro da <style> e o HTML não precisa ser delimitado por alguma tag. Além disso, essas partes podem vir em qualquer ordem, então o código abaixo também é válido:

<style>
    h1 {
        /* estilos de h1 */
    }
</style>

<h1>Hello {nome}!</h1>
<p>
    Minha primeira aplicação Svelte!
</p>

<script>
    let nome = 'World';
</script>

Note também que o HTML do componente não precisa ser envolto por uma tag, como no exemplo acima, que utilizamos as tags <h1> e <p>.

Estado

Em React, para criarmos um estado, precisamos explicitá-lo no código utilizando useState. Já no Svelte, qualquer variável que criamos com a palavra-chave let se torna um estado por padrão.

Ainda, em React, se quisermos alterar o estado nome para um novo valor no clique de um botão, podemos escrever o seguinte:

<button onClick={() => setNome('Antônio')} disabled={nome === 'Antônio'}>
Alterar nome
</button>

O código acima ficaria assim em Svelte:

    <button on:click={() => nome = 'Antônio'} disabled={nome === 'Antônio'}>
        Alterar nome
    </button>

Repare que utilizamos a diretiva on: para escutar o evento de click do botão. Note também que precisamos apenas fazer uma atribuição direta ao estado nome, e a interface do componente será re-renderizada de acordo com a mudança. Trata-se de uma sintaxe intuitiva e prática, especialmente, quando trabalhamos com objetos e arrays.

Diretivas são como “atributos especiais” que colocamos em tags do HTML. Elas já são conhecidas em Angular e Vue.js, e são um recurso poderoso, que podem nos ajudar de diversas formas no nosso desenvolvimento.

Two-way data binding

Vamos criar um input que altera o estado nome que criamos no código React, utilizando a função setNome:

      <input
        type="text"
        value={nome}
        onChange={(e) => setNome(e.target.value)}  
      />

Note que precisamos declarar o atributo value={nome} para que o estado defina o valor inicial do campo, e também declarar o atributo onChange={(e) => setNome(e.target.value)} para que as alterações no campo alterem o estado também.

No Svelte, podemos simplificar essas operações utilizando a seguinte sintaxe:

<input type="text" bind:value={nome} />

Usamos a diretiva bind: para fazer um Two-way data binding (Ligação de dados bidirecional) que, nesse caso, serve para ligar (ou vincular) um atributo do HTML a um estado. Dessa forma, o atributo value e o estado nome sempre possuirão o mesmo valor.

Estilos escopados

No React, por padrão, os estilos não são escopados, ou seja, se arquivos CSS declararem estilos para um mesmo seletor, esses estilos irão interferir entre si. Soluções possíveis são utilizar módulos CSS ou Styled Components.

Já no Svelte, os estilos são escopados por padrão, pois esse é o comportamento que geralmente queremos. Se, por acaso, precisarmos que algum estilo seja global para todos os componentes, podemos escrever a seguinte sintaxe:

    :global(h1) {
        /* estilos de h1 */
    }

Utilizamos o modificador :global() e, dentro dos parênteses, colocamos o seletor CSS que queremos globalizar.

Estrutura de condição

No React, combinamos o JS com JSX para renderizar HTML de forma condicional, como nesse código:

    {
        nome === 'Antônio'
            ? <p>É meu nome!</p>
            : <p>Não é meu nome...</p>
    }

Diferentemente, no Svelte, temos uma estrutura dedicada para essas situações, e o código ficaria assim:

    {#if nome === 'Antônio'}
        <p>É meu nome!</p>
    {:else}
        <p>Não é meu nome...</p>
    {/if}

Esse é o bloco #if do Svelte, e pode ser utilizado, opcionalmente, com cláusulas :else if e :else.

Estrutura de repetição

Em React, podemos combinar o JS com JSX para iterar sobre alguma lista e renderizar HTML de acordo com ela. Considere que temos um estado chamado numeros, que é um array do JavaScript. Para imprimir um parágrafo para cada item do array, faríamos algo assim:

    {numeros.map((numero) => (
        <p>Número: {numero}</p>
    ))}

Já no Svelte, temos um estrutura dedicada para esses casos, e nosso código ficaria assim:

    {#each numeros as numero}
        <p>Número: {numero}</p>
    {/each}

Esse é o bloco #each do Svelte e ele pode até ser utilizado junto com uma cláusula :else, que mostra um HTML caso a lista esteja vazia.

Note que esses blocos especiais sempre começam com #, “continuam” com : (quando há cláusulas) e terminam em /.

Código reativo

Às vezes, no nosso código, é útil guardar valores que dependem de algum estado do componente. Em React, logo após a declaração do estado nome, poderíamos adicionar o seguinte código:

const meuNome = nome === 'Antônio';

Assim, podemos utilizar meuNome no botão e no condicional:

    <button onClick={() => setNome('Antônio')} disabled={meuNome}>
        Alterar nome
    </button>

    {
        meuNome
            ? <p>É meu nome!</p>
            : <p>Não é meu nome...</p>
    }

Dessa forma, evitamos repetição de código, além de aumentarmos a legibilidade e a facilidade de manutenção. Entretanto, o código const meuNome = nome === 'Antônio'; é executado sempre que o componente é re-renderizado, mesmo que essa renderização tenha sido causada por um estado que não fosse nome.

Por outro lado, no Svelte, todo o código dentro da tag <script> é executado uma única vez, quando o componente é renderizado pela primeira vez na tela. Então, como faríamos para replicar a situação acima?

Na tag <script>, podemos adicionar o seguinte código:

$: meuNome = nome === 'Antônio';

Assim, no HTML, podemos utilizar meuNome:

<button on:click={() => nome = 'Antônio'} disabled={meuNome}>
    Alterar nome
</button>

{#if meuNome}
    <p>É meu nome!</p>
{:else}
    <p>Não é meu nome...</p>
{/if}

A sintaxe $: indica que um código deve ser reativo! O Svelte identifica quais estados estão sendo utilizados nessa sintaxe e executa o código quando algum desses estados é alterado. Assim, meuNome = nome === 'Antônio' é executado somente quando o estado nome for alterado.

Se você já trabalhou com Vue.js, talvez tenha lembrado das computed properties (propriedades computadas). De fato, a “sintaxe de dólar” funciona praticamente da mesma forma.

Componentes, Ciclo de Vida e Gerenciamento de Estado

Fizemos a comparação entre conceitos fundamentais do Svelte e do React, mas ainda levaríamos vários artigos para cobrirmos mais diferenças importantes! Algumas delas:

Comunicação entre componentes

No React, a comunicação básica entre componentes se dá de forma unidirecional e sempre do pai para o filho, através de props. Já o Svelte fornece várias opções pra gente, como props, dispatch (filho para o pai) e bind (comunicação bidirecional).

Composição de componentes

No React, para passarmos conteúdos mais complexos para um componente filho, podemos utilizar children. No Svelte, utilizamos o slot, que nos dá uma grande variedade de recursos, como definir um conteúdo padrão (fallback), configurar o recebimento de mais de um conteúdo (named slots), entre outros.

Métodos de ciclo de vida

Na abordagem funcional do React, o controle dos ciclos de vida de um componente é unificado no hook useEffect(). O Svelte prefere separar essas responsabilidades em diferentes métodos: onMount(), beforeUpdate(), afterUpdate() e onDestroy(). Mas também temos a opção de retornar uma função para o método onMount(), e ela será executada quando o componente for destruído, ou seja, como se ela estivesse no método onDestroy().

Gerenciamento de estado

No React, podemos optar pela solução nativa, a Context API, ou alguma biblioteca externa, como Redux. No Svelte, temos duas soluções nativas: as Stores, para gerenciamento de estado global, e uma Context API também, para casos mais específicos.

Conclusão: Svelte é melhor que React?

Apesar de todos os benefícios citados, o Svelte ainda é uma tecnologia em ascensão, e não possui tantas oportunidades de emprego quanto seus concorrentes.

Por outro lado, ele já é utilizado por empresas como Spotify, The New York Times, Avast, Philips, e outras, como podemos ver na página principal do Svelte e nessa página da extensão Wappalyzer, que analisa quais sites utilizam determinada tecnologia.

Captura de tela de uma parte da página oficial do Svelte, com um texto em inglês que significa “Quem está usando Svelte?”. Abaixo desse texto, aparecem as logomarcas das seguintes empresas: 1Password, Allaska Airlines, Avast, Chess.com, FusionCharts, GoDaddy, IBM, Les Echos, Philips, Rakuten, Razorpay, Square, The New york Times e Transloadit.

Captura de tela do site oficial do Svelte.

O React ainda lidera o mercado e as vagas de emprego. Mas nós, pessoas desenvolvedoras front-end, devemos sempre nos manter atualizadas de novas tecnologias, principalmente, quando possuem um grande potencial de crescimento, como o Svelte. Além disso, estudar diferentes ferramentas front-end é uma excelente forma de reforçar conceitos e de apurar nosso senso crítico, fazendo-nos questionar as decisões que foram tomadas na construção de uma determinada tecnologia.

Se interessou pelo Svelte? Você pode conferir nossa formação Svelte para mergulhar ainda mais nessa ferramenta. Além disso, você aprenderá sobre o SvelteKit, que também vem conquistando a comunidade dev!

Confira também esse Hipster Ponto Tube: Como trabalhar com Framework SVELTE? Com Mario Souto.

Antônio Evaldo
Antônio Evaldo

Instrutor e Desenvolvedor de Software nas escolas de Front-end e de Programação da Alura, com foco em JavaScript. Sou técnico em Informática pelo IFPI e cursei Engenharia Elétrica na UFPI. Sou apaixonado por desenvolvimento web e por compartilhar conhecimento de forma encantadora. No tempo livre, assisto séries, filmes e animes.

Veja outros artigos sobre Front-end