Este é um pequeno artigo de resposta à publicação
"Comparação de estruturas JS: React, Vue e Hyperapp" . Em geral, eu não sou um grande fã dessas comparações. No entanto, como estávamos falando de uma estrutura marginal como a Hyperapp, em comparação com mastodontes como React e Vue, pensei, por que não considerar os mesmos exemplos no
Svelte . Por assim dizer, para completar a imagem. Além disso, leva literalmente 5 minutos. Vamos lá!

Se de repente você não estiver familiarizado com o
Svelte e o conceito de estruturas em desaparecimento, poderá ler os artigos
“Magically Disappearing JS Framework” e
“Disappearing Framework” .
Para conveniência dos leitores, copiei os exemplos do
artigo original sob os spoilers para facilitar a comparação. Bem, vamos começar.
Exemplo nº 1: contra-aplicação
Reagirimport React from "react"; import ReactDOM from "react-dom"; class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0}; } down(value) { this.setState(state => ({ count: state.count - value })); } up(value) { this.setState(state => ({ count: state.count + value })); } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick = {() => this.down(1)}>-</button> <button onClick = {() => this.up(1)}>+</button> </div> ); } } ReactDOM.render(<Counter />, document.querySelector("#app"));
Vue import Vue from "vue"; new Vue({ data: { count: 0 }, methods: { down: function(value) { this.count -= value; }, up: function(value) { this.count += value; } }, render: function(h) { return( <div> <h1>{this.count}</h1> <button onClick={() => this.down(1)}>-</button> <button onClick={() => this.up(1)}>+</button> </div> ); }, el: "#app" });
Hyperapp import { h, app } from "hyperapp"; const state = { count: 0 }; const actions = { down: value => state => ({ count: state.count - value}), up: value => state => ({ count: state.count + value}) }; const view = (state, actions) => ( <div> <h1>{state.count}</h1> <button onclick={() => actions.down(1)}>-</button> <button onclick={() => actions.up(1)}>+</button> </div> ); app(state, actions, view, document.querySelector("#app"));
▍Svelte
<div> <h1>{count}</h1> <button on:click="set({count: count - 1})">-</button> <button on:click="set({count: count + 1})">+</button> </div>
→ Um
exemplo de trabalho.▍Análise
Um componente
Svelte é um arquivo html que possui o notório formato SFC (Single File Component), de uma forma ou de outra, já usado no
Vue ,
Ractive ,
Riot e em outras estruturas. Além do próprio modelo html, um componente pode ter o comportamento e a lógica descritos em javascript, além de estilos de escopo do componente.
Nenhuma parte do componente é necessária; portanto, o componente do contador pode consistir apenas no modelo html do próprio contador. Para alterar o valor da variável
count , o manipulador de cliques usa o método interno do componente
set () descrito na
documentação .
Exemplo No. 2: Trabalhando com Código Assíncrono
Reagir import React from "react"; import ReactDOM from "react-dom"; class PostViewer extends React.Component { constructor(props) { super(props); this.state = { posts: [] }; } getData() { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { this.setState(state => ({ posts: json})); }); } render() { return ( <div> <button onClick={() => this.getData()}>Get posts</button> {this.state.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); } } ReactDOM.render(<PostViewer />, document.querySelector("#app"));
Vue import Vue from "vue"; new Vue({ data: { posts: [] }, methods: { getData: function(value) { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { this.posts = json; }); } }, render: function(h) { return ( <div> <button onClick={() => this.getData()}>Get posts</button> {this.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); }, el: "#app" });
Hyperapp import { h, app } from "hyperapp"; const state = { posts: [] }; const actions = { getData: () => (state, actions) => { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { actions.getDataComplete(json); }); }, getDataComplete: data => state => ({ posts: data }) }; const view = (state, actions) => ( <div> <button onclick={() => actions.getData()}>Get posts</button> {state.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); app(state, actions, view, document.querySelector("#app"));
▍Svelte
<div> <button on:click="getData()">Get posts</button> {#each posts as {title, body}} <div> <h2><font color="#3AC1EF">{title}</font></h2> <p>{body}</p> </div> {/each} </div> <script> export default { methods: { getData() { fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(posts => this.set({ posts })); } } }; </script>
→ Um
exemplo de trabalho.▍Análise
Diferentemente do JSX, que, como uma cópia carbono, é usado em todas as três estruturas da comparação original e, na verdade, estende o código javascript com sintaxe semelhante a html, o
Svelte usa recursos mais familiares - incorporando códigos js e css em html usando
< script> e
<style> .
O script do componente exporta um objeto JS simples, dividido em seções. A seção
métodos descreve métodos de componentes que podem ser usados por meio da instância do componente e nos manipuladores de eventos. Portanto, quando você clica no botão, o método
getData () é
chamado , dentro do qual os dados são solicitados e, após a conclusão da operação, os dados são simplesmente instalados no estado do componente e imediatamente desenhados no modelo.
Observe o uso da destruição do objeto de publicação (postagem) em cada etapa da iteração da lista de publicações:
{#each posts as {title, body}}
Esse truque evita redundância em modelos como
{post.title} e simplifica visualmente os modelos usando uma entrada mais curta
{title} .
Exemplo 3: componente de item de lista para um aplicativo de Tarefas Pendentes
Reagir (estilo funcional) function TodoItem(props) { return ( <li class={props.done ? "done" : ""} onclick={() => props.toggle(props.id)}> {props.value} </li> ); }
Reagir class TodoItem extends React.Component { render () { return ( <li class={this.props.done ? "done" : ""} onclick={() => this.props.toggle(this.props.id)}> {this.props.value} </li> ); } }
Vue var TodoItem = Vue.component("todoitem", { props: ["id", "value", "done", "toggle"], template: '<li v-bind:class="{done : done}" v-on:click="toggle(id)">{{value}}</li>' });
Hyperapp const TodoItem = ({ id, value, done, toggle }) = ( <li class={done ? "done" : ""} onclick={() => toggle(id)}> {value} </li> );
▍Svelte
<li class="{done ? 'done' : ''}" on:click="set({done: !done})">{value}</li>
→ Um
exemplo de trabalho.▍Análise
Tudo é bastante banal aqui. Nós expomos a classe css dependendo do valor
concluído e alteramos esse valor para o oposto quando você clica em um item da lista.
Comparação dos métodos do ciclo de vida dos componentes
Isenção de responsabilidade : A partir de agora, decidi omitir a comparação com o Hyperapp, porque, caso contrário, as tabelas seriam simplesmente ilegíveis.▍Análise
O Svelte é extremamente minimalista, inclusive em termos de ganchos do ciclo de vida. Existem apenas 4 ganchos:
- onstate - chamado antes da criação do componente e cada estado muda antes da atualização do DOM.
- oncreate - o momento em que o componente é criado é chamado.
- onupdate - chamado imediatamente após a montagem no DOM e cada estado muda após a atualização do DOM.
- ondestroy - chamado quando o componente é destruído e removido do DOM.
Comparação de desempenho da estrutura
Sinceramente, não sei no que comentar. Os próprios benchmarks e a maneira como são executados sempre causam muita controvérsia, então não acho que faça sentido concentrar desnecessariamente a atenção.
No entanto, ainda não temos outros dados.
▍Trabalhando com tabelas

OadCarregando, iniciando, tamanhos de código

▍Trabalhando com memória

▍Análise
A julgar pelos números, o
Svelte é bastante rápido, "consome" pouca memória (inclusive porque não usa o VirtualDOM), é iniciado rapidamente e tem um tamanho pequeno.
Em geral, não posso dizer que os resultados dos benchmarks dessas três estruturas diferiram drasticamente. No entanto, apenas o
Svelte possui uma coluna exclusivamente "verde", ou seja, é bastante bom ao mesmo tempo em todos os aspectos, o que significa que está perfeitamente equilibrado e não possui distorções óbvias no consumo de velocidade ou memória ou em outras métricas. Em geral, com ele, você pode iniciar com segurança qualquer projeto, da Web habitual, para dispositivos móveis, Smart TV e sistemas mais exóticos.

Sumário
O Svelte é uma ótima ferramenta para criar componentes de praticamente qualquer aplicativo da web. É tão poderoso quanto o React e, embora tenha uma comunidade significativamente menor, exige menos esforço para dominar. É flexível, como o Vue, enquanto é muito mais minimalista e verificado, pois não tenta captar de uma só vez todas as idéias do desenvolvimento da web moderna.
Além disso, ele é o único que usa o conceito de
estruturas ameaçadas . Em outras palavras, ele não possui
tempo de execução específico além do próprio navegador.
Os aplicativos são rápidos, não exigem recursos e são pequenos em tamanho. Além disso, o
Svelte pode ser "perfeitamente" usado em aplicativos escritos em outras estruturas, sobre as quais planejo escrever na próxima vez.
Se você conheceu essa estrutura maravilhosa pela primeira vez, pode estar interessado em ler outros artigos sobre ela:
→
Desaparecendo Magicamente o JS Framework→
Preenchimento automático de 1 KB→
SvelteJS: Lançamento da segunda versãoSe você ainda tiver dúvidas sobre o
Svelte , entre no
canal de telegrama em russo
SvelteJS . Lá, você sempre pode fazer uma pergunta e obter conselhos, descobrir as últimas notícias e apenas conversar. Teremos o maior prazer em vê-lo!