Categorias

Conhecendo Svelte

Uma das principais características de um bom desenvolvedor é a constante busca por uma forma otimizada de se fazer as mesmas coisas de antes. Não se trata de reinventar a roda, mas a perpétua insatisfação com a forma como a roda funciona e a necessidade de torná-la melhor, mais rápida, mais eficiente, mais robusta ou mais segura.

Entre tantas tecnologias e formas de se fazer as coisas, percebemos que, até então, não havia conteúdo de Svelte no Código Fonte. Nada melhor que abrir um ano novo com um novo horizonte, uma nova técnica para se aprender, comparar e adotar (ou não). O que o Svelte propõe é uma abordagem descomplicada que merece sua atenção.

Josh Collinsworth é um desenvolvedor front-end, designer, professor e escritor. Ele atualmente mora em Omaha, Nebraska, e trabalha para o Shopify como desenvolvedor de front-end sênior. Em um artigo publicado na internet, ele traz uma imersão completa em Svelte para quem não conhece e compara a solução com outras abordagens, como Vue e React.

Com sua autorização, traduzimos e reproduzimos o artigo na íntegra:

“Vamos ser honestos: muitas coisas no desenvolvimento da web são mais difíceis do que deveriam ser. Alguns dias, pode parecer que tudo no mundo do front-end é desnecessariamente e excessivamente projetado e complicado.

Isso é o que faz Svelte parecer uma lufada de ar fresco.

O que é Svelte?

Em um nível básico, você poderia pensar em Svelte como uma estrutura de interface de usuário (IU) de front-end semelhante a React, Vue, etc. Svelte é o mais novo dos grandes nomes no espaço, no entanto, e definitivamente parece que aprendeu com os outros, em termos de experiência do desenvolvedor e otimização.

Como acontece com qualquer estrutura de front-end, você usa o Svelte para construir componentes, que são os blocos de construção para sua interface de usuário (IU). Conforme os eventos acontecem e o estado e os dados mudam (por exemplo: um usuário adicionando um item ao carrinho), os componentes são atualizados automaticamente para refletir essas mudanças na IU. Mais sobre isso em breve.

Então, em que Svelte é diferente? Que bom que você perguntou…

Qual a diferença de Svelte?

Svelte foi criado por Rich Harris, desenvolvedor e editor gráfico do New York Times.

O mundo das notícias se move rápido, então as interfaces de usuário e visualizações interativas que Harris estava criando para o Times precisavam ser construídas o mais rápido possível. Mas, uma vez que é fundamental que as notícias sejam acessíveis a todos, esses bits de interatividade também deveriam ser tão pequenos e eficientes quanto possível.

Harris precisava de uma solução que fosse extremamente rápida e fácil de construir, mas que fosse rápida e fácil para qualquer leitor em qualquer dispositivo ou rede, não importando o quão limitado. Em muitos casos, os pacotes de JavaScript inchados que são subprodutos de muitos outros frameworks os desqualificaram de consideração. Então Harris decidiu construir sua própria solução, e foi assim que Svelte nasceu.

Embora relativamente novo e pequeno em comparação com os outros frameworks na lista, Svelte é exclusivamente testado em batalha: o mapa Covid do New York Times é um aplicativo Svelte. (O empregador de Harris está longe de ser a única grande empresa que emprega a tecnologia, no entanto; IBM, Square, Philips, 1Password e Spotify estão entre sua lista crescente de usuários).

A atenção à experiência do desenvolvedor (DX) é óbvia no Svelte. Eu imediatamente amei como isso tornava fácil tudo o que eu queria fazer – especialmente em comparação com React, conforme eu tuítei descaradamente na época:

Desde o início, fiquei consistentemente e agradavelmente surpreso com o pouco código que eu precisava para fazer as coisas no Svelte – e como estava perto do JavaScript, HTML e CSS que eu já conhecia.

Na verdade, tive que desaprender muitas das soluções mais complicadas comuns em outros frameworks (um refrão comum para os adotantes do Svelte).

Quase em todos os lugares que eu normalmente tentaria uma solução alternativa ou tropeçaria em um problema ao usar outra estrutura, Svelte era deliciosamente direto.

Mas, em vez de eu falar sobre isso, vamos fazer algumas comparações. (Uma vez que isso não tem a intenção de ser um “mão no código”, vamos cobrir a instalação do Svelte no final).

Comparando Svelte com React e Vue

Conforme mencionado, em um nível básico, Svelte é semelhante a outros frameworks de front-end. Então, vamos olhar um pouco mais de perto nos detalhes de como o Svelte difere: seu foco no tempo de construção sobre o tempo de execução e a simplicidade de sua sintaxe.

Construir no navegador

Já mencionei como os aplicativos Svelte têm desempenho. Isso é possível porque Svelte tem uma abordagem diferente de outros frameworks de front-end, fazendo o máximo que pode na etapa de construção – quando o código é compilado inicialmente – em vez de executar no lado do cliente.

Se você quiser ser técnico, o Svelte não é realmente um framework JavaScript, tanto quanto é um compilador.

Para elaborar: React, Vue e a maioria dos outros frameworks são executados no navegador. Você os carrega primeiro e depois os usa chamando seus métodos para executar qualquer código que você escrever (não muito diferente do jQuery e inúmeras bibliotecas semelhantes). Você pode carregar React, Vue, etc. em uma tag de script, em um CodePen, ou então soltá-los em qualquer ambiente que desejar. Provavelmente há uma ferramenta de construção envolvida para reduzir o tamanho do pacote quando você trabalha com esses frameworks em um ambiente de produção. Entretanto, pelo menos até certo ponto, você está inevitavelmente enviando a própria estrutura para o navegador e carregando-a lá.

Svelte não funciona assim; você não pode “carregar o Svelte” no navegador ou brincar com ele no CodePen (embora o Svelte REPL funcione bem). Svelte não é um script.

Em vez disso, para criar um aplicativo Svelte, você instala o repositório Svelte em sua máquina e escreve o código Svelte – que, tecnicamente falando, é um pequeno superconjunto de HTML. O compilador faz o resto: Todo o seu código Svelte é compilado em um JavaScript mínimo e autocontido antes mesmo de chegar ao navegador.

Não é diferente de como o Sass é compilado para CSS simples. É por isso que Svelte foi referido como “um framework sem framework”. O REPL oferece uma visão direta do JavaScript compilado, se você estiver interessado.

Essa abordagem permite tamanhos de pacote extremamente pequenos, o que por sua vez se traduz em melhor velocidade de carregamento e desempenho. Um pacote menor pode ser enviado ao navegador com mais rapidez e analisado pelo navegador mais velozmente.

O React e o Vue também usam um “DOM virtual” para renderização, que – embora seja mais rápido do que rastrear o próprio DOM para fazer alterações – ainda tem suas próprias implicações de desempenho. Graças ao compilador Svelte, no entanto, não precisamos nos preocupar com isso; componentes são vinculados diretamente a seus nós DOM. Você pode ler mais sobre isso com Rich Harris em “Virtual DOM is pure overhead“.

Há um pouco mais de nuances do que isso ao discutir o desempenho de Svelte em relação ao campo, mas entraremos nisso na última seção.

Criação de componentes Svelte

Uma das coisas que mais gosto no Svelte é sua filosofia de HTML em primeiro lugar. Com poucas exceções, o código Svelte é HTML e JavaScript inteiramente legível por navegador. Na verdade, tecnicamente, você poderia chamar o código Svelte como um pequeno superconjunto de HTML.

Mas chega de falar; vamos mostrar.

Assim como você grava arquivos de componente .jsx em arquivos React e .vue em Vue, Svelte tem arquivos de componente .svelte. Um componente Svelte pode ter a seguinte aparência (embora você possa ordenar as peças da maneira que quiser):

<script>
// Lógica do componente vai aqui
</script>

<!-- HTML vai aqui -->

<style>
/* CSS vai aqui (com escopo padrão!) */
</style>

Vamos ver um exemplo real.

Talvez a maneira mais manjada de demonstrar uma estrutura de front-end seja um componente de botão que conta quantas vezes foi clicado. É o “hello world” dos exemplos de componentes:

Não é um exemplo particularmente prático, mas é comum porque é uma maneira eficaz de demonstrar o arroz com feijão dos frameworks de front-end: faça um pequeno componente para rastrear seu estado (a contagem) e sempre que algo fizer com que o estado mude ( o clique), atualiza automaticamente a IU (o botão).

Veja os exemplos abaixo para comparar este componente em diferentes frameworks:

<!-- CounterButton.svelte -->
<script>
	let count = 0

	const incrementCount = () => {
		count++
	}
</script>

<button on:click={incrementCount}>
  Number of clicks: {count}
</button>
// CounterButton.jsx
import React, { useState } from 'react'

export const CounterButton = () => {
  const [count, setCount] = useState(0)

  const handleClick = () => {
    setCount(count + 1)
  }

  return (
    <button onClick={handleClick}>
      Number of clicks: {count}
    </button>
  )
}
<!-- CounterButton.vue -->
<script>
  export default {
    data: () => ({
      count: 0
    }),

    methods: {
      incrementCount() {
        this.count++
      }
    }
  }
</script>

<​template>
  <button @click="incrementCount">
    Number of clicks: {{ count }}
  </button>
</template>
<!-- CounterButton.vue -->
<script setup>
  import { ref } from 'vue'

  const count = ref(0)

  const incrementCount = () => {
    count.value++
  }
</script>

<​template>
  <button @click="incrementCount">
    Number of clicks: {{ count }}
  </button>
</template>

Nota: Eu uso as funções de seta e omito o ponto-e-vírgula nesses exemplos, mas isso é apenas preferência estilística pessoal.

Existem algumas diferenças importantes que gostaria de apontar entre a versão Svelte e as outras:

  • Svelte é reativo por padrão. Isso significa que quando uma variável é reatribuída, cada lugar que é usada ou referenciada também é atualizado automaticamente. Tanto o React quanto o Vue exigem que você inicialize explicitamente as variáveis ​​reativas.O React, em particular, faz isso por causa de uma insistência na “imutabilidade”. Sua filosofia dita que você não deve ser capaz de alterar o valor de uma variável sem chamar uma função que está “autorizada” para fazer isso.Em teoria, isso evita mutações indesejadas (mudanças), mas na prática, 99% das vezes, é clichê desnecessário.
  • A versão Svelte é a mais curta, tanto em termos de contagem de linhas quanto de caracteres. Embora isso não seja necessariamente significativo por si só, um código mais curto tende a ser menos sujeito a erros, desde que seja legível (o que eu diria que definitivamente é).
  • Svelte não é exigente com HTML. React precisa de um retorno com um único elemento, e Vue precisa de uma única tag <template> envolvendo toda a marcação. (Vue 2 também requer um único elemento dentro dele.) Svelte pode ter qualquer HTML, em qualquer lugar – e com todos os seus atributos intactos, ao contrário de JSX, a linguagem de modelagem de fato do React.

Um exemplo mais prático de botão de alternar

Mostrar ao usuário quantas vezes ele clicou em um botão não é particularmente prático, então vamos ver algo um pouco mais realista; um botão que alterna algum conteúdo oculto:

Este exemplo é pelo menos próximo da funcionalidade do mundo real; acredito que não é muito difícil imaginar como algo semelhante a isso seria útil em um cenário de produção.

Gosto deste exemplo porque apresenta dois conceitos-chave de estrutura:

  1. Renderização condicional – instruções if dentro da marcação; e
  2. Valores calculados – variáveis dinâmicas que mudam dependendo da situação (neste caso, o texto do botão).

Vamos comparar como Svelte, React e Vue lidam com esses conceitos:

<!-- ToggleButton.svelte -->
<script>
  let isTextShown = false
  
  const toggleIsTextShown = () => {
    isTextShown = !isTextShown
  }

  $: buttonText = isTextShown ? 'Show less' : 'Show more'
</script>

<p>
  Svelte is a JavaScript framework.
  
  {#if isTextShown}
    Though actually, if you want to get technical...
  {/if}
</p>

<button on:click={toggleIsTextShown}>
  {buttonText}
</button>
// ToggleButton.jsx
import React, { useState } from 'react'

export const ToggleButton = () => {
  const [isTextShown, setIsTextShown] = useState(false)

  const handleClick = () => {
    setIsTextShown(!isTextShown)
  }

  const buttonText = isTextShown ? 'Show less' : 'Show more'

  return (
    <div>
      <p>
        Svelte is a JavaScript framework.
        
        {isTextShown && 
          `Though actually, if you want to get technical...`
        }
      </p>

      <button onClick={handleClick}>
        {buttonText}
      </button>
    </div>
  )
}
<!-- ToggleButton.vue -->
<script>
  export default {
    data: () => ({
      isTextShown: false
    }),

    methods: {
      toggleIsTextShown() {
        this.isTextShown = !this.isTextShown
      }
    },

    computed: {
      buttonText() {
        return this.isTextShown ? 'Show less' : 'Show more'
      }
    }
  }
</script>

<​template>
  <div>
    <p>
      Svelte is a JavaScript framework.
    
      <​template v-if="isTextShown">
        Though actually, if you want to get technical...
      </template>
    </p>

    <button @click="toggleIsTextShown">
      {{ buttonText }}
    </button>
  </div>
</template>
<!-- ToggleButton.vue -->
<script setup>
  import { ref, computed } from 'vue'

  const isTextShown = ref(0)

  const toggleIsTextShown = () => {
    isTextShown.value = !isTextShown.value
  }

  const buttonText = computed(() => (
    isTextShown.value ? 'Show less' : 'Show more'
  ))
</script>

<​template>
  <p>
    Svelte is a JavaScript framework.
  
    <​template v-if="isTextShown">
      Though actually, if you want to get technical...
    </template>
  </p>

  <button @click="toggleIsTextShown">
    {{ buttonText }}
  </button>
</template>

A maneira de Svelte de lidar com valores calculados é aquele operador $: que você vê acima; acrescente isso a qualquer nome de variável e ele será reavaliado toda vez que algo depender de alterações. Neste caso, buttonText é reavaliado cada vez que isTextShown muda.

O React permite que você faça algo semelhante, mas o Vue os move para funções computed.

Outras diferenças dignas de nota:

  • Svelte e Vue 3 não exigem que você “envolva” sua marcação em um único elemento. React e Vue 2 sim. Eu não ficaria surpreso se o React descobrisse uma maneira de eliminar esse requisito em breve, no entanto.
  • No React e no Vue, você precisa envolver os elementos condicionais em HTML e / ou sequenciá-los. Svelte permite que você coloque qualquer marcação válida que você quiser dentro dos blocos #if, e não exige que você os vincule a um elemento.

A acessibilidade deste exemplo de botão de alternância é questionável, por uma questão de brevidade. Eu recomendo por Heydon Pickering o artigo Building Inclusive Toggle Buttons para mais informações.

Comparando formulários

Aqui está um último exemplo rápido e prático, para comparar ligações de formulário entre frameworks: um controle deslizante de volume. Experimente:

<!-- VolumeControl.svelte -->
<script>
  let volume = 0
</script>


<label for="volume-control">
  Volume: {volume}%
</label>

<input 
  id="volume-control"
  type="range"
  min="0"
  max="100"
  bind:value={volume}
/>
// VolumeControl.jsx
import React, { useState } from 'react'

const VolumeControl = () => {
  const [volume, setVolume] = useState(0)
  
  return (
    <div>
      <input 
        id="colume-control"
        type="range"
        min="0"
        max="100"
        value={volume}
        onChange={(e) => setVolume(e.target.value)} 
      />

      <label for="colume-control">
        Volume: {volume}%
      </label>
    </div>
  )
}
<!-- VolumeControl.vue -->
<script>
  export default {
    data: () => ({
      volume: 0
    })
  }
</script>

<​template>
  <div>
    <label for="volume-control">
      Volume: {{ volume }}%
    </label>

    <input 
      id="volume-control"
      type="range"
      min="0"
      max="100"
      v-model="volume"
    />
  </div>
</template>
<!-- VolumeControl.vue -->
<script setup>
  import { ref } from 'vue'

  const volume = ref(0)
</script>

<​template>
  <label for="volume-control">
    Volume: {{ volume }}%
  </label>

  <input 
    id="volume-control"
    type="range"
    min="0"
    max="100"
    v-model="volume"
  />
</template>

Observe especialmente como o fluxo de dados do React é unilateral; ele precisa que você atualize explicitamente a variável de volume sempre que sua entrada correspondente mudar. Em outras palavras: você precisa fazer a entrada ler a configuração de volume e atualizar a configuração de volume, em duas etapas diferentes.

Por outro lado, tanto o Svelte quanto o Vue oferecem vinculação de dados bidirecional; você apenas diz à estrutura que sempre que a entrada ou o valor muda, o outro deve ser atualizado para refletir isso.

Também deve ser observado que você também pode adicionar vinculação de dados bidirecional aos adereços de componente no Svelte:

<ChildComponent bind:someProp={someValue} />

Isso permitiria que o ChildComponent passasse as alterações para o componente pai e vice-versa. React é firmemente contra essa ideia porque, novamente, valoriza muito a imutabilidade e o fluxo de dados unilateral. Na prática, pessoalmente acho esse dogma mais inibidor do que útil.

Comparando lógica

Embora já tenhamos visto, acho que vale a pena dar uma olhada mais uma vez em como cada uma das três estruturas lida com a renderização condicional. Veja como você mostraria um componente <Hello /> condicionalmente:

{#if isShown}
  <Hello />
{/if}
{
  isShown && <Hello />
}
<Hello v-if="isShown" />

Não estou distinguindo entre Vue 2 e 3 nesses exemplos porque sua sintaxe de modelagem é idêntica.

É claro que você também pode fazer else (e else if se for esse o caso, embora eu não faça uma demonstração disso só porque escrever a expressão React seria um pesadelo).

Aqui está um exemplo onde mostramos um componente <WelcomeBanner /> se o usuário estiver conectado, e um componente de formulário de login caso contrário:

{#if isUserLoggedIn}
  <WelcomeBanner />
{:else}
  <LoginForm />
{/if}
{
  isUserLoggedIn 
    ? <WelcomeBanner />
    : <LoginForm />
}
 <WelcomeBanner v-if="isUserLoggedIn" />
  <LoginForm v-else />

Loops

Eu aprecio como o Svelte permite loops dentro da marcação, sem exigir que você vincule o loop a nenhum elemento ou mapear sobre uma matriz (e na maioria dos casos, sem exigir que você utilize key em cada item).

Aqui, suponha que temos uma matriz chamada posts, cheia de objetos contendo informações de postagem:

{#each posts as post}
  <h2>
    <a href={post.link}>
      {post.title}
    </a>
  </h2>

  <p>{post.excerpt}</p>
{/each}
posts.map(post => (
  <div>
    <h2>
      <a href={post.link}>
        {post.title}
      </a>
    </h2>

    <p>{post.excerpt}</p>
  </div>
))
<div v-for="post in posts">
  <h2>
    <a :href="post.link">
      {{ post.title }}
    </a>
  </h2>

  <p>{{ post.excerpt }}</p>
</div>

Também é bom que você possa colocar qualquer marcação que desejar dentro de cada bloco de Svelte; não precisa ser um único elemento.

Outras razões para se amar Svelte

Embora os exemplos acima não cubram, existem algumas outras características do Svelte que adoro:

  • Tudo vive junto em um arquivo. Semelhante aos componentes .vue de arquivo único, os arquivos .svelte mantêm a lógica, a marcação e os estilos do seu componente juntos. Veremos mais sobre isso na próxima seção.
  • CSS com escopo padrão por padrão. Veremos mais sobre Svelte CSS na próxima seção também.
  • Transições e animações integradas. Uma API integrada robusta significa que não há necessidade de recorrer a uma biblioteca externa ou transformações visuais de código à mão.
  • Armazenamentos de dados reutilizáveis ​​integrados (pense em uma versão muito leve e simples do Redux ou Vuex)
  • Atalhos fáceis para associação de classe, passagem de prop e modificadores de evento (que sinto falta agora ao trabalhar com outros frameworks)

Eu poderia continuar falando sobre como o Svelte torna as coisas fáceis e como ele parece avançado, mas simples. Até mesmo o site de documentos e tutoriais de Svelte está muito à frente do jogo; a coisa toda é um REPL (ambiente de codificação) ao vivo, onde você pode escrever seu próprio código Svelte e vê-lo rodando ao vivo!

CSS em Svelte

Uma das minhas partes favoritas no Svelte é como ele torna divertido e fácil o uso de estilos.

Para adicionar estilos a um componente no Svelte, você simplesmente cria uma tag <style> no arquivo .svelte do componente. Qualquer CSS dentro dele terá como escopo o componente por padrão.

Se preferir, você pode usar Sass em seus componentes com modificações mínimas e adicionando lang = “scss” à tag <style>. Isso é possível graças ao svelte-preprocess.

Svelte Preprocess tem suporte para várias “linguagens” (incluindo Sass, PostCSS e TypeScript) embutidas. Além disso, o svelte-preprocess adiciona um recurso Sass extremamente bom: você pode especificar o conteúdo para preceder ao carregar o Sass do seu componente.

Dessa forma, se você tiver todas as suas variáveis Sass em um arquivo _vars.scss externo como eu, você pode apenas fazer com que o processador importe automaticamente para cada componente. Isso evita que você tenha o trabalho de fazer @import manualmente o arquivo SCSS com várias ../../../ para atravessar o sistema de arquivos toda vez que quiser usar uma variável em um componente.

Estilo condicional

O estilo condicional é uma moleza em Svelte, graças às suas abreviações simples. Vejamos um pouco mais de perto como você pode aplicar uma classe .enabled a um componente, com base em um valor booleano:

<script>
  let enabled = false
</script> 

<input class={enabled ? 'enabled' : ''} />

Isso funciona, e se você usou um estilo condicional em outros frameworks, pode ter recorrido a algo semelhante. Mas os ternários podem ser um pouco prolixo e difíceis de ler, especialmente quando um dos lados nem mesmo está fazendo nada.

Como no React, você pode encurtar isso para uma condicional de “curto-circuito”:

<script>
  let enabled = false
</script> 

<input class={enabled && 'enabled'} />

Isso também funciona, mas não é tão idiomático quanto eu gostaria, pessoalmente; a menos que você já esteja familiarizado com o React, pode não perceber o que o operador && está fazendo nesta situação.

Como alternativa, em Svelte, podemos apenas fazer isso:

<script>
  let enabled = false
</script> 

<input class:enabled={enabled} />

Isso é bem legal! Também é mais fácil de ler; você pode simplesmente ver qual classe será aplicada, com base no valor de JS.

Podemos dar um passo adiante, no entanto: se o nome da classe e o nome da propriedade forem idênticos, você pode simplesmente fazer isso:

<script>
  let enabled = false
</script> 

<input class:enabled />

Uau! Que legal. É basicamente uma abreviação de valor de propriedade de objeto ES6 para classes condicionais.

Também vale a pena mencionar: você pode ter quantos atributos class desejar (dinâmicos ou não) em um único elemento:

<div
  class="layout"
  class:logged-in={isLoggedIn}
  class:darkMode
  class:reduceMotion
>
  <!-- ...Content here -->
</div>

Estilo de escopo versus global

Se desejar tornar o CSS de um componente global, você pode fazer isso por regra com a função :global ():

<style>
  ul {
    /* This CSS applies ONLY to the component */

    :global(li) {
      /* These styles are global */
    }
  }
</style>

Ou, se preferir, você pode tornar a tag inteira global com o atributo global:

<style global>
  /* All CSS here is global */
</style>

Uma palavra de aviso, no entanto: estilos globais podem persistir uma vez carregados na página, uma vez que Svelte produz os estilos de seu componente como um arquivo CSS autônomo. Portanto, se você tiver uma tag de estilo global em um componente que carrega apenas condicionalmente, seus estilos podem permanecer mesmo depois que o componente for removido da página, potencialmente aplicando-se aos elementos lá também.

Isso pode levar a alguma confusão, uma vez que “global” significa global apenas uma vez carregado; o componente deve ser montado uma vez antes que esses estilos estejam realmente disponíveis.

Por causa disso, descobri que é uma boa ideia sempre usar um seletor de classe pai como container, mesmo ao lidar com estilos com escopo definido.

Na pior das hipóteses, é redundante e, na melhor das hipóteses, você se salvou do vazamento de estilo não intencional (seja agora ou se decidir desfazer o escopo dos estilos no futuro).

Se você gostaria de ler mais sobre estilos no Svelte, certifique-se de ler o artigo What I Like About Writing Styles with Svelte em CSS Tricks.

Adereços e comunicação de componentes

Eu aprecio a flexibilidade incorporada ao Svelte. Isso é evidente na maneira como permite que você passe dados e eventos entre componentes.

Se você gosta da maneira como o React lida com as coisas, pode passar métodos para seus componentes filhos e manter o fluxo unilateral intacto.

Se você gosta do $emit do Vue, pode despachar eventos personalizados de componentes filhos e ouvi-los no pai.

Como mencionado acima, você também pode fazer bind de adereços para habilitar o fluxo de dados bidirecional ou apenas ter ambos os componentes inscritos na mesma loja Svelte – ou até mesmo misturar e combinar. A escolha é sua.

Para criar um adereço em um componente Svelte, você simplesmente cria uma variável usando a palavra-chave export:

<script>
  export let propToBePassedIn
</script>

O acima indica um adereço requerido; se você quiser criar um adereço opcional, basta dar a ele um padrão:

<script>
  export let propToBePassedIn = false
</script>

Essa sintaxe pode parecer um pouco estranha no início, já que geralmente estamos acostumados a exportar como uma forma de distribuir as coisas. É reconhecidamente uma das peculiaridades de Svelte, mas se torna familiar rapidamente. Pense nisso como um componente que exporta a responsabilidade por um valor para um componente pai.

Vamos fazer uma última comparação, apenas para ver como isso é feito em outros frameworks:

<!-- PageHeading.svelte -->
<script>
  export let pageTitle
  export let pageSubtitle = ''
</script>

<h1>
  {pageTitle}
  {#if pageSubtitle}
    <small>{pageSubtitle}</small>
  {/if}
</h1>
// PageHeading.jsx
const PostPreview = ({ pageTitle, pageSubtitle }) => {
  return (
    <h1>
      {pageTitle}
      {pageSubtitle &&
        <small>{pageSubtitle}</small>
      }
    </h1>
  )
}
<!-- PageHeading.vue -->
<script>
  export default {
    props: {
      pageTitle: {
        required: true
      },
      pageSubtitle: {
        default: ''
      }
    }
  }
</script>

<​template>
  <h1>
    {{ pageTitle }}
    
    <small v-if="pageSubtitle">
      {{ pageSubtitle }}
    </small>
  </h1>
</template>
<!-- PageHeading.vue -->
<script setup>
  const props = defineProps({
    pageTitle: {
      required: true
    },
    pageSubtitle: {
      default: ''
    }
  })
</script>

<​template>
  <h1>
    {{ pageTitle }}
    
    <small v-if="pageSubtitle">
      {{ pageSubtitle }}
    </small>
  </h1>
</template>

Em qualquer um dos casos acima (já que ambos os adereços são apenas strings), você usaria o componente da seguinte maneira:

<PageHeading
  pageTitle="The big page title text…"
  pageSubtitle="…and a little subheading"
/>

Algumas coisas a serem destacadas:

  • Observe que o React não tem nenhum tipo de adereço, ou qualquer forma de exigir um adereço. Você precisaria importar uma biblioteca para isso, provavelmente PropTypes. Você poderia, é claro, escrever à mão a lógica no componente, mas isso não se ajusta bem.
  • Embora o Svelte permita que você defina os adereços necessários, ele não tem a digitação de adereços embutida, como o Vue faz. Isso ocorre principalmente porque Svelte é totalmente compatível com TypeScript. A expectativa parece ser: se você quiser digitação de adereço, pode simplesmente usar o TypeScript para isso.

O que saber sobre Svelte

Vou ser honesto: para mim, quaisquer argumentos contra a adoção de Svelte ficam cada vez mais escassos. Entretanto, vou mencionar algumas coisas que você deve saber e alguns dos argumentos a favor e contra Svelte aqui, apenas para ter perspectiva, se nada mais.

Desmascarando o argumento da “pequena comunidade”

Ao comparar Svelte (ou qualquer tecnologia mais recente, nesse caso) com concorrentes maiores e mais estabelecidos, os argumentos contra a adoção geralmente apontam para o tamanho da comunidade. Onde React, Vue, Angular, etc. todos têm grandes ecossistemas cheios de recursos para você aproveitar, Svelte pode parecer comparativamente pequeno.

O medo, então, é que quando ou se você precisar buscar pacotes adicionais para lidar com coisas além das capacidades da estrutura principal, você pode ser deixado em apuros.

Eu gostaria de contextualizar esse argumento:

  1. Muitas vezes você não precisa de pacotes com Svelte. Quando você está usando o mesmo framework por muito tempo, é fácil esquecer que o motivo pelo qual você precisa de um pacote em primeiro lugar é muitas vezes a compatibilidade (ou a necessidade de contornar) o framework em si.Svelte está muito mais próximo do HTML, CSS e JavaScript da web, o que significa que você não precisa frequentemente procurar um pacote que, digamos, funcione bem com os ganchos do seu framework ou métodos de ciclo de vida. Além disso, muitos dos recursos para os quais você precisaria de um pacote em outros frameworks vêm incorporados ao Svelte (movimento, CSS com escopo e gerenciamento de estado sendo os maiores exemplos).
  2. Svelte é extremamente compatível com pacotes JavaScript padrões. Isso significa que, embora, sim, o ecossistema de pacotes e plug-ins dedicados do Svelte seja comparativamente pequeno, ele pode frequentemente se beneficiar e usar facilmente qualquer pacote agnóstico de framework – que é uma grande parte dos pacotes por aí.
  3. Mesmo quando você precisa construir algo sozinho, o SvelteKit torna isso relativamente simples. Um exemplo: anteriormente, eu estava usando um plugin RSS com Gridsome, mas não existe tal pacote para SvelteKit.Uma rápida pesquisa na web, no entanto, foi suficiente para encontrar uma maneira muito fácil de criar um feed RSS no SvelteKit, sem dependências, em menos de 40 linhas de código.

Sim, Svelte escala

Já falamos sobre como os componentes do SvelteKit são compilados e enviados como JavaScript autocontido mínimo, o que significa que não há sobrecarga de um framework. Essa abordagem leva a pacotes menores, mas a desvantagem é: também há menos código compartilhado, então cada componente individual inevitavelmente conterá código repetido.

Carregar um script de framework antecipadamente adiciona carga inicial, mas quanto mais seu código é reutilizado, mais compensa – o que significa que acima de uma certa escala, a vantagem da abordagem de Svelte é neutralizada e é realmente mais eficiente para construir com outra solução.

Isso faz com que algumas pessoas afirmem que Svelte não escala, mas isso é prematuro.

A verdadeira questão que importa é: onde está esse ponto? Claramente, ninguém está preocupado se o React escala, então quando Svelte perde sua vantagem sobre o React?

Acontece que a escala em que as vantagens de Svelte desaparecem é na verdade irrealisticamente alta para praticamente qualquer aplicação.

Se desejar mais detalhes, você pode ler esta comparação de dimensionamento do pacote React e Svelte ou esta comparação semelhante. Porém, para resumir ambos: a vantagem de Svelte desaparece em algum lugar em torno de 150 kB de componentes carregados na página. Isso não parece muito, mas os componentes são minúsculos; na verdade, seria necessário um número bem grande (ou complexidade extremamente alta) para chegar a esse ponto. Muitos componentes não têm nem 1 kB. Na verdade, os testes de velocidade me decepcionaram por não fazer o g-zip de componentes, uma vez que o Netlify não aplica gzip automaticamente a nenhum componente com menos de 1 kB de tamanho, pois os ganhos são pequenos demais para se preocupar.

Para efeito de comparação: recentemente reescrevi este site no SvelteKit. Entendo que  ainda é um pequeno site pessoal e não um aplicativo de produção, mas eu mal estou a 20% do caminho para essa escala em qualquer rota. Meu maior e mais complexo componente – o arquivo __layout.svelte, que tem 17 importações – tem apenas 12 kB. Nenhum dos meus outros componentes tem 3 kB. Portanto, é difícil entender como eu faria uma página grande e complexa o suficiente para se aproximar do vértice de ~ 150 kB, dado que estou ordens de magnitude abaixo disso agora. E apenas para enfatizar/esclarecer: isso é por rota, não o aplicativo como um todo.

Além disso, não vamos esquecer: essa é a escala em que você está em pé de igualdade com o React. Você ainda teria que ir significativamente mais longe do que isso antes que houvesse qualquer diferença significativa entre os dois.

Além disso, toda essa discussão se concentra em como as coisas estão agora, neste momento, e não nas vantagens futuras. O React ficará menor e mais rápido no futuro? Provavelmente; é apoiado por uma grande e talentosa equipe. Contudo, ele também se beneficiou de quase uma década de otimização; então pode não haver muito o que extrair dela neste momento.

Por outro lado, Svelte é comparativamente jovem. Se estou apostando em qual framework irá melhorar mais no futuro em relação à sua posição atual, estou apoiando Svelte, sem dúvida.

Vale a pena mencionar que, desde que o Svelte começou a se tornar popular, outros frameworks aprenderam com ele e fecharam um pouco a lacuna de desempenho. Em geral, o React ainda é significativamente mais pesado, mas o Vue 3 é bastante comparável ao Svelte em termos de desempenho em muitos casos.

Svelte não é compatível com o Internet Explorer por padrão

Svelte requer polyfills para funcionar corretamente no Internet Explorer (e, mesmo assim, o suporte para qualquer versão do IE abaixo de 11 não é garantido).

Se você precisar suportar o IE 11, pode ler o problema Svelte/IE11 GitHub, que lista algumas possíveis soluções alternativas e polyfills. Ou pode ser um caso em que a escolha de outro framework seja necessário.

No entanto, se você está começando um novo projeto hoje: observe que o Internet Explorer não vai permanecer por muito tempo nesse mundo. A pesquisa do Google recentemente abandonou o suporte para o IE 11, citando sua pequena e cada vez menor participação de mercado (apenas cerca de 1% de todos os navegadores). O WordPress, que abastece cerca de 40% da web neste momento, abandonou o suporte para o IE 11 na versão 5.8 do WordPress no início deste ano. E até a própria Microsoft colocará o prego final no caixão do IE 11 em julho de 2022.

Quais são seus objetivos?

A resposta para a pergunta sobre se você deve usar o Svelte agora é um clássico: “depende”.

Você está aprendendo seu primeiro framework? Se sim, qual é o seu objetivo? Se você está procurando uma ferramenta fácil de aprender, algo que irá capacitá-lo a construir IUs interativas, ou apenas algum conhecimento e experiência adicionais, eu recomendo Svelte de todo o coração.

Não há escolha errada quando se trata de desenvolver suas próprias habilidades – particularmente porque ter uma solução básica torna muito mais fácil aprender uma nova, como passar de um instrumento para outro.

Por outro lado, se você está aprendendo na esperança de conseguir um emprego com suas novas habilidades, seria difícil recomendar qualquer coisa além de React para essa busca – simplesmente porque é o maior framework de longe em termos de participação de mercado e empregos disponíveis. Eu gostaria que não fosse o caso, mas a tecnologia como um todo (nos EUA, pelo menos), entrou fortemente no React e não vejo isso mudando tão cedo. Ainda assim: se você já conhece React, acho que ainda vale a pena aprender Svelte apenas pela perspectiva, se nada mais.

Alternativamente: você está escolhendo uma tecnologia para uma startup ou projeto relativamente novo? O Svelte provavelmente permitirá que você se mova mais rapidamente e construa algo com melhor desempenho, mas contratar ou colaborar pode ser um desafio, dado o conjunto relativamente pequeno de desenvolvedores Svelte. Dito isso, no entanto: conhecer um framework JS tende a tornar o aprendizado de um novo mais fácil, e Svelte é, em minha opinião, o mais fácil para começar. Acho que qualquer desenvolvedor que já esteja familiarizado com outra solução de front-end deve ser capaz de aprender o Svelte muito rapidamente (e vice-versa).

Svelte brilha em ambientes limitados

Eu mencionei isso na introdução, mas um dos maiores pontos fortes de Svelte são seus tamanhos mínimos de pacote de JavaScript. Isso o torna ideal para qualquer código que será executado por dispositivos de baixo consumo que não conseguem analisar JavaScript rapidamente (smart TVs, relógios e outros dispositivos IoT, por exemplo, ou smartphones mais antigos que podem ser mais comuns em mercados menos favorecidos economicamente) . Isso também significa que o Svelte brilha onde a largura de banda é limitada, o que novamente o torna um ajuste perfeito para dispositivos mais antigos e usuários que podem estar com conexões de internet ruins.

Reatividade com matrizes e objetos

A única “pegadinha” notável de Svelte está em como ele lida com a reatividade automática com matrizes e objetos. Você pode ler mais sobre isso no tutorial do Svelte sobre matrizes e objetos, mas para resumir: modificar uma matriz ou objeto não será registrado no Svelte como uma atualização e, portanto, não causará uma nova renderização. Você precisa reatribuir a variável para forçar o Svelte a reconhecer a mudança.

<script>
let colors = ['red', 'orange', 'yellow']

colors.push('green')
// ❌ Updates the array, but doesn't cause a re-render

colors = [...colors, 'blue']
// ✅ Reassigning causes a re-render
</script>

O mesmo princípio funciona com objetos, também:

<script>
let me = {
  firstName: 'Josh'
}

me.lastName = 'Collinsworth'
// ❌ Updates the object, but doesn't cause a re-render

me = {...me, lastName: 'Collinsworth' }
// ✅ Reassigning causes a re-render
</script>

Se por algum motivo você tiver que usar .push (), você poderia apenas atribuir o array a ele mesmo depois. Isso funcionaria:

myArray.push(newThing)
myArray = myArray

Mas eu acho que isso é um pouco melhor (e funciona exatamente da mesma maneira):

myArray = [...myArray, newThing]

Se você quiser ficar nerd por um segundo: isso é na verdade uma peculiaridade do próprio JavaScript, e não do Svelte. JavaScript ainda considera a matriz ou objeto como a mesma coisa única a menos que seja reatribuído. É por isso que você pode usar const para declarar uma matriz ou objeto e ainda modificar suas propriedades; a variável em si não foi alterada, embora seu conteúdo tenha.

Como começar com Svelte

Se você gostaria de mergulhar e ter alguma experiência prática com Svelte (e eu recomendo que você faça!), Existem duas maneiras principais de avançar neste ponto.

The Svelte REPL

Obviamente, sou um grande fã, então posso ser tendencioso, mas honestamente acho que Svelte pode ter o melhor tutorial e documentação de qualquer framework por aí.

Há uma introdução maravilhosa no Tutorial Svelte, que funciona como um ambiente de codificação ao vivo onde você aprende Svelte pouco a pouco e tenta terminar os desafios de código Svelte incompletos ao longo do caminho. Ou, se quiser, você pode apenas clicar em “mostrar” para ver a lição completa. É divertido e envolvente e cobre todos os conceitos de Svelte, do simples ao complexo, extremamente bem. Na verdade, eu me pego voltando a isso indefinidamente. Eu recomendo fortemente tanto para aprendizado quanto para referência.

Iniciando seu próprio projeto Svelte

Como alternativa, há um guia de início rápido do Svelte que o orienta durante a instalação do Svelte em sua máquina. Vou postar as instruções aqui também; é surpreendentemente rápido, supondo que você já tenha o NPM instalado:

npx degit sveltejs/template my-svelte-project
cd my-svelte-project
# to use TypeScript run:
# node scripts/setupTypeScript.js

npm install
npm run dev

Se você não estiver familiarizado com esses comandos:

  • npx permite que você execute algo do NPM, mas sem realmente instalá-lo em sua máquina. Neste caso, queremos apenas executar o degit uma vez; não precisamos mantê-lo por perto para nada depois.
  • degit clona um repositório (neste caso, o projeto template de sveltejs), mas sem seu histórico git; será como se você estivesse iniciando um novo projeto.

Naturalmente, você pode substituir my-svelte-project por qualquer nome que desejar para o seu projeto local. Depois de rodar o npm install, o npm run dev iniciará um servidor de desenvolvimento que mostrará seu projeto e será atualizado automaticamente conforme você salva as alterações.

Conclusão

Espero que você esteja tão animado com Svelte quanto eu! Eu encorajo você a experimentar por conta própria, mesmo que seja apenas brincando no tutorial do Svelte. Se você ainda não experimentou, acho que ficará agradavelmente surpreso com o quão relativamente simples é.

E se você quiser se aprofundar, há também o SvelteKit, uma estrutura de aplicativo Svelte para projetos maiores/mais complexos. Eu escrevi uma postagem sobre a conversão deste site em SvelteKit da Gridsome, se você quiser dar uma olhada também.”

Publicado originalmente como “Introducing Svelte, and Comparing Svelte with React and Vue” em 1º de outubro de 2021. Traduzido e republicado com autorização do autor.