9 pontos por GN⁺ 2025-02-19 | 7 comentários | Compartilhar no WhatsApp
  • Resumo dos problemas enfrentados após atualizar recentemente uma aplicação web para o Svelte 5
    • Surgiram comportamentos inesperados por causa do recurso de deep reactivity e do ciclo de vida alterado
  • Gostei muito do Svelte 3/4 por bastante tempo, mas daqui para frente acho que não vou escolher Svelte para novos projetos

Necessidade de velocidade

  • A equipe do Svelte tentou otimizar desempenho por meio de deep reactivity, e conseguiu extrair uma performance melhor
  • Antes disso, ele já oferecia bom desempenho por meio do processo de compilação, e isso era um diferencial em relação a outros frameworks
  • Isso acabou criando um framework opaco, difícil de depurar, mas parecia um trade-off aceitável em termos de desempenho e produtividade

Necessidade de velocidade

  • A principal mudança em que a equipe do Svelte está apostando no Svelte 5 é a “deep reactivity”, para aumentar o desempenho com uma reatividade mais granular
  • Nas versões anteriores do Svelte, esse objetivo era alcançado principalmente com o compilador do Svelte
    • O fato de o desenvolvedor não precisar aprender conceitos novos diretamente e poder reorganizar a lógica interna com facilidade destacava a originalidade do Svelte
  • Ao mesmo tempo, esse processo de compilação também tornava o framework opaco, dificultando a depuração de problemas complexos
    • Bugs no próprio compilador geravam erros cuja causa era difícil de identificar, e às vezes só era possível resolver refatorando totalmente o componente problemático
  • Ainda assim, parecia um compromisso razoável entre velocidade e produtividade, então eu tolerava até o incômodo de ter de reinicializar o projeto periodicamente

Svelte não é Javascript

  • O Svelte 5 duplica esse trade-off
  • A diferença central é que o ponto de compromisso entre abstração e desempenho deixou de ficar só na etapa de compilação e passou a penetrar também na parte de runtime
    • Uso de proxies para dar suporte a deep reactivity
    • Estado implícito do ciclo de vida do componente
  • Essas duas mudanças melhoram o desempenho e fazem a API para desenvolvedores parecer mais elegante
  • O que haveria para não gostar? Infelizmente, esses dois recursos podem ser considerados exemplos típicos de leaky abstraction
    • No fim, isso cria um ambiente mais complexo para o desenvolvedor lidar

Proxies não são objetos

  • Com o uso de Proxy, a equipe do Svelte conseguiu extrair um pouco mais de desempenho do framework sem exigir trabalho extra do desenvolvedor
    • Em frameworks como React, ao passar estado por vários componentes, é comum provocar rerenders desnecessários; o Svelte introduziu Proxy para reduzir isso
    • O compilador do Svelte já evitava alguns problemas que poderiam surgir no processo de diff do virtual DOM, mas aparentemente a equipe concluiu que Proxy poderia melhorar ainda mais o desempenho
    • A equipe do Svelte também mencionou que Proxy contribui para melhorar a experiência do desenvolvedor, defendendo a ideia de que “é possível maximizar tanto a eficiência quanto a facilidade de uso”
  • O problema é que o Svelte 5 parece mais simples na superfície, mas na prática adiciona mais abstrações
    • Por exemplo, usar Proxy para detectar métodos de array traz a vantagem de não precisar escrever código como value = value no Svelte 4
    • No Svelte 4, o desenvolvedor precisava entender até certo ponto como o compilador funcionava para disparar a reatividade. Já no Svelte 5, passa-se a impressão de que “dá para esquecer o compilador”, mas na prática não é assim
    • Na mesma medida em que a nova abstração traz conveniência, também aumenta o número de regras que o desenvolvedor precisa conhecer para que o compilador se comporte como esperado
  • Depois de usar Svelte por muito tempo, pessoalmente fui passando a usar mais Svelte stores e menos declarações reativas
    • Svelte stores são, em essência, mais próximas de conceitos do JavaScript, a forma de chamar o método update é simples, e a sintaxe $ era mais um benefício adicional
    • Assim como as declarações reativas, Proxy causa o problema de “parecer uma coisa, mas se comportar de forma diferente nas bordas”
  • Quando usei o Svelte 5 pela primeira vez, tudo parecia funcionar bem, mas ao tentar salvar estado com Proxy no IndexedDB, ocorreu um DataCloneError
    • Pior ainda, para saber com certeza se um valor é Proxy, é preciso tentar uma clonagem estruturada com try/catch, o que tem custo de desempenho
    • No fim, você passa a ter de lembrar o que é Proxy e usar $state.snapshot toda vez em contextos externos que não reconhecem Proxy
    • Como resultado, ao contrário da intenção original de que “a abstração aumenta a conveniência do desenvolvedor”, isso acaba impondo regras e procedimentos mais complexos

Componentes não são funções

  • Por volta de 2013, o virtual DOM ganhou popularidade porque permitia modelar aplicações como composição de funções
    • O Svelte vinha mantendo uma abordagem de usar o compilador em vez de virtual DOM para simplificar funções de ciclo de vida e melhorar desempenho
    • Porém, no Svelte 5, o conceito de ciclo de vida foi reintroduzido de forma semelhante aos React Hooks
  • Em React, Hooks são uma abstração que reduz o código relacionado a estado dos métodos de ciclo de vida
    • O código fica mais limpo, mas há muitos pontos em que o desenvolvedor precisa tomar cuidado, como ao referenciar estado dentro de setTimeout
    • Mesmo no Svelte 4, já podia haver problema se código assíncrono acessasse elementos do DOM no momento em que o componente fosse desmontado
    • Agora, no Svelte 5, parece ter sido adicionado estado implícito ao ciclo de vida do componente para coordenar mudanças de estado e efeitos
  • A documentação oficial sobre $effect explica o seguinte:
    > “$effect pode ser colocado em qualquer lugar, mas deve ser chamado durante a inicialização do componente (ou enquanto um efeito pai estiver ativo), e desaparece quando o componente (ou o efeito pai) é desmontado”
  • Isso sugere que, ao contrário da explicação de que o ciclo de vida só tem duas etapas, mount/unmount, existe uma estrutura de efeitos complexa que exige rastrear mudanças de estado
  • A documentação oficial do ciclo de vida diz que “before update/after update não existem”, mas surgem novos conceitos como $effect.pre e tick
  • Na prática, isso significa que é preciso entender não apenas mount/unmount, mas também os momentos em que o estado muda
  • O ponto que causou problema no uso real foi que até estado passado para funções não relacionadas ao Svelte fica preso ao ciclo de vida do componente
  • Por exemplo, foi usado um padrão de gerenciar modais por store e passar callbacks para um componente filho
    const { value } = $props()  
    const callback = () => console.log(value)  
    const openModal = () => pushModal(MyModal, { callback })  
    
  • Se esse código estiver dentro do componente modal, o componente que chamou o modal será desmontado primeiro, e nesse momento value passa a undefined
  • Há um exemplo mínimo de reprodução publicado nesse repositório
  • Ou seja, props referenciadas por um callback que continua vivo mesmo após o fim do ciclo de vida do componente de repente viram undefined
  • Esse é um comportamento diferente do JavaScript básico, e faz parecer que o Svelte está fazendo algum tipo de coleta de lixo por conta própria
  • Pode haver razões de engenharia para isso, mas é um comportamento inesperado e surpreendente

Conclusão

  • O que é fácil certamente tem seu apelo, mas, como disse Rich Hickey, fácil não significa simples
  • Como Joel Spolsky diz, eu não gosto de comportamentos inesperados
  • O Svelte mostrou muita “mágica” ao longo do tempo, mas nesta versão, a quantidade de coisas que é preciso memorizar para usar essa mágica aumentou tanto que o custo superou o benefício
  • O objetivo deste texto não é criticar a equipe do Svelte; pelo contrário, reconheço que há muita gente que prefere o Svelte 5 (e React Hooks)
  • O importante é o equilíbrio entre oferecer conveniência ao usuário e permitir que o usuário mantenha o controle
  • Software realmente bom não se baseia em “esperteza”, e sim em “entendimento”
  • À medida que ferramentas de IA evoluem, torna-se importante escolher ferramentas que aproveitem a sabedoria já acumulada e ajudem na compreensão profunda, em vez de ferramentas que façam você não saber o que está fazendo
  • Obrigado a Rich Harris e à equipe por toda a experiência agradável de desenvolvimento até aqui. Espero que este texto sirva como um feedback que não seja totalmente impreciso

7 comentários

 
firea32 2025-02-24

proxy é conveniente para quem cria, mas deixa quem precisa depurar irritado kkk

 
bichi 2025-02-21

Meu projetinho paralelo tem o melhor DX com solidjs >m< / felicidade

 
pcj9024 2025-02-20

Acho que, por existirem alternativas como o Svelte, React/nextjs também pôde receber um grande estímulo.
Fundamentalmente, o Svelte é uma language, então espero que ele também mostre bem a direção que uma linguagem para descrever UI deve seguir.

Eu vou usar React

 
iolothebard 2025-02-20

Excesso faz mal
Desvio do caminho
Camada sobre camada

 
colus001 2025-02-20

Acho que mudou de um jeito estranho, sendo bastante influenciado por React e especialmente pelo Next. +page é difícil de entender se você olhar sem conhecer Svelte, e runes como $state e $derived parecem estar seguindo o React; sinceramente, a época em que se colocava $: antes das variáveis me parecia melhor. Dá para tolerar uma sintaxe antiga como {#each a in array} {/each}, mas ainda assim continua incômoda. Se a ideia é melhorar o desempenho com reatividade opcional, acho que o SolidJS segue uma direção muito melhor. Como ele usa JSX diretamente, também é relativamente mais fácil migrar vindo de React. É até estranho o quanto o SolidJS recebe relativamente pouca atenção.

 
xiniha 2025-02-19

Parece que os Signals estão caminhando para o Trough of disillusionment do Gartner hype cycle 🤔 Conforme os casos de uso vão se consolidando gradualmente, acho que a avaliação pode melhorar.

 
GN⁺ 2025-02-19
Comentários no Hacker News
  • No começo eu não me interessei muito pelos runes. Mas mudei de ideia quando percebi que era possível importar componentes externos reativos em templates .svelte e encapsular a reatividade internamente. Isso significa que dá para escrever testes com vitest e ainda aproveitar os benefícios da reatividade. Isso é realmente poderoso e, AFAIK, algo único no mundo frontend

    • A maioria dos desenvolvedores frontend simplesmente não testa nada. TypeScript é a ferramenta que as pessoas usam para garantir correção, e há um motivo para isso. Mas os usuários de Svelte sempre tiveram uma visão limitada sobre TypeScript, e também há um motivo para isso
    • Pessoalmente, prefiro escrever código frontend testável, e o Svelte 5 é revolucionário nesse aspecto. É reativo no navegador, mas tão bom quanto testes unitários
    • Dito tudo isso, o post do blog está dizendo a verdade. Adicionar proxies parece bem desconfortável. React e Vue me perderam quando começaram a empilhar abstração sobre abstração, e os proxies foram o ponto de partida disso
    • O fato de Svelte 5 não ser JavaScript é <i>o motivo de eu gostar do Svelte 5</i>
    • Acho que existem duas formas principais e razoáveis de fazer frontend/web
        1. HTML estático ou templates renderizados no servidor, talvez HTMX
        1. Linguagens/plataformas que compilam para JavaScript. No mínimo TypeScript, mas como eu realmente acho que HTML e CSS são muito bons, JSX, React, Tailwind etc. ficam <i>de fora</i>, e o Svelte 5 junto com alguns outros frameworks são de fato uma melhoria em relação ao TypeScript puro
    • Svelte 5 é o vencedor claro na categoria 2
    • Tem templates HTML excelentes, propagação de estado fácil e sensata, e recursos que facilitam escrever código modular. Funciona bem com CSS e muitas vezes permite criar apps e ferramentas simples e descartáveis em um ou dois arquivos, além de também servir para aplicações maiores e mais sérias. É menos mágico e surpreendente que o Svelte 4 e, honestamente, é agradável de usar. Felizmente, não me importo com IndexedDB
    • Hoje em dia eu realmente não vejo motivo algum para escrever uma linha de JavaScript, mas cada um faz do seu jeito
  • Estou desenvolvendo ativamente uma aplicação SvelteKit distribuída comercialmente e queria compartilhar algumas impressões da experiência

    • O que me atraiu no SvelteKit no começo foi sua simplicidade. Depois de configurar o projeto, eu podia trabalhar em um arquivo HTML/JS/CSS por vez, enquanto aproveitava as vantagens de um framework moderno sem a complexidade. Isso me lembrava os primeiros tempos do desenvolvimento web, quando tudo funcionava só de colocar arquivos HTML em um servidor Apache
    • Mas é decepcionante ver o Svelte se afastando desse paradigma simples. Desde o início, Rich Harris apresentou a facilidade de uso e a simplicidade do Svelte como pontos centrais de venda. A versão atual do SvelteKit não é ruim, mas eu preferia a anterior. Naquela época, não era preciso lidar com estruturas de roteamento como +page. Você podia colocar arquivos Svelte onde quisesse, e eles eram renderizados sem atrito, enquanto você ainda tinha os benefícios de um framework moderno
    • Essas mudanças adicionam uma complexidade que antes não era necessária e podem afastar o apelo original do Svelte. Escolhi com base no que já conhecia
  • É uma pena que EmberJS tenha desaparecido. A API foi bastante estável nos últimos 10 anos. Ironicamente, alguém que escreveu apps em EmberJS ao longo da última década provavelmente teria menos dificuldade para migrar do que alguém que fez o mesmo trabalho com React, Svelte, Vue etc.

    • Infelizmente, a equipe do Ember tomou algumas decisões estranhas no começo, e ele não era fácil de entender em comparação com JavaScript comum (embora a maior parte disso já tenha sido corrigida)
    • Ser ou não JavaScript importa muito menos do que a estabilidade da API
    • Pessoalmente, meu problema com JavaScript é que ele muda com frequência demais
  • Os dois links de Github listados pelo autor no topo do post apontam para o mesmo problema, e esse problema tem solução (use $state.raw)

    • Sou fã do Svelte desde a versão 2 ou 3. Isso porque era a coisa mais próxima de escrever HTML/CSS/JS puro e ainda ter os benefícios de um framework (além de usar Sass e TypeScript). Fantástico
    • O Svelte 5 me deixou apreensivo porque os runes pareciam estranhos. Depois de atualizar meu projeto e trabalhar em outros, não é tão ruim assim. O Svelte 5 não permite misturar o jeito antigo e o novo de lidar com estado, e as mensagens de erro em geral são informativas
    • Vejo gente nos comentários dizendo que htmx e JS puro são objetivamente melhores... não? Talvez para o que você faz. Pessoalmente, o Svelte ainda é muito mais fácil de entender do que React. Para quem se importa com benchmarks, o Svelte é tão rápido quanto o SolidJS (acho que usuários de React conseguiriam migrar facilmente para Solid, a sintaxe parece semelhante)
  • Svelte 5 é a <i>pior</i> forma de não ser JavaScript. Ele não resolve os problemas do js e oferece abstrações vazadas para alguns problemas de frontend. Acho que o Solid segue uma direção melhor que a do Svelte. O Solid não depende de uma nova linguagem. Mas existe um impulso para criar algo que não seja js porque js não é ideal. Elm é um precursor do svelte. Mas acho que dá para fazer algo melhor...[0]

  • Comecei a usar Svelte 5 porque eu realmente odiava as stores no Svelte 4. Estou usando Sveltekit e Svelte 5 em um projeto novo e preciso dizer... a produtividade do React continua imbatível, mesmo que a tecnologia do Sveltekit e do Svelte seja tecnicamente melhor

    • Algumas coisas que realmente me irritaram: todas as páginas têm nomes como +page.server.ts ou +page.svelte ou alguma variação disso, então fica difícil buscar código com facilidade. As ferramentas do Svelte existem separadamente de tsc e ESLint, o que torna mais difícil integrá-las ao CI e usá-las no desenvolvimento
    • Também existem problemas estranhos de compatibilidade com versões anteriores. Por exemplo, a maioria dos pacotes Svelte ainda usa stores, então você precisa lutar com dois mundos de versões, e escrever código às vezes fica realmente confuso. Além disso, o HMR do Svelte ainda parece estar no começo, então o recarregamento de módulos Svelte acaba bagunçando o estado
    • Eu realmente quero gostar de Svelte. A renderização é bem rápida e gosto das ideias por trás dele. Mas a produtividade do React é imbatível
  • Dizer que Svelte não é JavaScript por causa de um comportamento inesperado ao passar closures em callbacks parece estranho. Um título melhor seria "Eu não gosto do Svelte 5 porque ele me surpreendeu"

  • Se você está procurando uma biblioteca com a qual possa construir componentes e apps usando JavaScript puro, dê uma olhada em Lit: Lit

    • Existe um pacote adicional de signals para reatividade profunda, com foco em integração com a futura proposta Signals do TC39: Signals
    • Lit é usado em apps importantes como Photoshop, Reddit, Home Assistant e The Internet Archive
  • Quer uma experiência frontend sensata? Use JavaScript puro, web components, htmx, Blazor

    • Frameworks JS são uma loucura, por qualquer motivo