Convertendo uma aplicação angular em sveltejs-pt.1

Tiago Vieira Mota
Tech Intelipost
Published in
8 min readDec 8, 2019
Svel… o que? Como é o nome do framework?

Apresentando o framework.

Como descrito no artigo explicativo, o svelte trata-se de framework ou biblioteca, como queiram denominar, para construção de componentes assim como os seus três maiores “concorrentes”: vue, react e angular. Porém, se destaca, por trabalhar de forma diferente dos outros frameworks, compilando o código escrito para Javascript puro sem levar o próprio do framework para o bundler final, ou seja, o svelte trabalha em tempo de compilação, não necessitando levar alguma dependência própria para funcionar. Por exemplo, o react necessita de dependências básicas para funcionar: react.js +react.dom.js(links).

Vejamos a tabela abaixo:

Fonte: https://www.codeinwp.com/blog/angular-vs-vue-vs-react/

Devido a esta característica, o framework vem ganhado notoriedade sendo utilizado em ambientes bem limitados em recursos, como pouca memória e pouco espaço de armazenamento. Um case conhecido é o gateway de pagamentos stone, que tem um toolkit de componentes desenvolvidos com svelte, que é utilizado para as interface visual da máquina de cartões.

No bestofjs, que classifica as bibliotecas Javascript pelo número de estrelas no github, o svelte já aparece no top 5 de tendências por média de estrelas/dia adicionadas anualmente.

Fonte: https://bestofjs.org/projects?tags=framework&sort=yearly

No stateofjs2018, o svelte ficou no topo das menções na secção “Outros frameworks” no item Front-end Frameworks. Acredito que na pesquisa de 2019, o svelte venha a aparecer em uma posição mais contundente nas próximas pesquisas, um mero palpite da minha parte.

A estrutura de um componente svelte é bem simples separando a parte Javascript dentro de uma tag <script> , o css dentro da tag <style> e após ou entre estas tags o html, algo parecido com os single file components do vuejs.

<script>
let name = ‘world’;
</script>
<h1>Hello {name}!</h1><style>
h1 {
color: red;
}
</style>

O que vamos construir?

Como o título do artigo sugere, vamos reescrever uma aplicação feita em angular.

PS. Fiz esta aplicação em angular quando estava aprendendo sobre a tecnologia, e ao longo do tempo fui incrementando o projeto e recentemente atualizei a versão do estável do angular(8.0). Tentei escrever em outros frameworks, mas não consegui por falta de tempo.

A proposta é simples, fazer uma pokedex utilizando a PokéAPI. A PokéAPI é uma API aberta, não é necessário fazer contas e conseguir APIKEYS para consumo da API, como é uma API “open” ela não é tão performática e não é tão bem estruturada, mas para serve muito bem para esta propósta que é construir uma aplicação simples.

O que vamos utilizar.

Para explicar a escolha do ParcelJs como module bundler(empacotador), vou começar pela escolha do TailwindCSS como biblioteca utilitária para o css. O tailwindcss é um utilitário para estilizar nossos componentes e páginas do projeto, o tailwind diferente das outras bibliotecas utilitárias(Bootstrap, Foundation, MaterialializeCSS) fornece classes básicas para tratar tamanhos(width, height), fontes, cores, espaçamento(padding, margin) e com essas classes contruir e estilizar componentes básicos como card e formulário, enquanto que seus concorrentes já nos disponibiliza um toolkit de componentes “prontos”.

Para compilar o tailwind com o svelte, é necessário a utilização de um pré-processador css, na documentação do tailwind é recomendado o uso do PostCSS, mas esta não é a única forma de se trabalhar com o tailwindcss.
O postcss é um “pre-processador” css, que permite a utilização de plugins para processar o css, como exemplo, foi utilizado no projeto o PurgeCSS que tem como objetivo remover o css inutilizado otimizando o css final gerado.

Explicado isso, vamos para o porquê do parceljs.

No guia de como iniciar com svelte uma das recomendações é utilizar o Degit como ferramenta para começar novos projetos, algo parecido com o create react app, temos como opções para module bundler(empacotadores) o rollup ou webpack. Mas durante as pesquisas e o desenvolvimento da aplicação, apesar de serem boas ferramentas para empacotamento do Javascript, optei por utilizar uma terceira opção para começar a “codar”, o parceljs. Tanto com o rollup quanto com o webpack, não consegui configurar ou pelo menos achar uma configuração para se utilizar o postcss para processar o css com o código do svelte. Existe um plugin do svelte para ser utilizado com o parceljs.
Para utilizar o parceljs não necessita de um arquivo de configuração(entrypoint) para compilar o projeto assim como no rollup e webpack, sendo necessário só apontar o index.html dentro do scripts dev ou build no package.json.

package.json

E dentro do index.html importar nosso arquivo de entrada Javascript.

Por nossa aplicação ser uma SPA(Single Page Application), é preciso uma biblioteca para trabalhar com rotas, e para isso utilizaremos o svero, que é desenvolvida pela comunidade do svelte, e acredito que seja umas das poucas para o svelte que fazem roteamento, e o svero tem uma abordagem parecida com o react router.

Iniciando o projeto

Feita as escolhas, vamos iniciar a construção da nossa pokedex. Para isso é primordial como primeiro requisito instalar ou ter instalado o nodejs. Após instalar, uma sugestão é instalar o yarn gerenciador de pacotes sendo uma alternativa ao npm que já vem com o nodejs.

Agora vamos criar uma pasta com o nome “svelte-parcel”, após isto, abrir o terminal, navegar até o diretório criado e executar o comando npm init e preencher as informações para iniciar um novo package.json. Para não preencher muitas informções basta executar npm init -y.

Agora vamos instalar nossas dependências, por o svelte se tratar de um compilador, nossas dependências serão instaladas como “devDependencies” e assim não as levando para o build final por isso a adição da flag -D.

yarn add parcel-bundler parcel-plugin-svelte parcel-plugin-svg-sprite svelte tailwindcss @fullhuman/postcss-purgecss -D

Por fim vamos adicionar a biblioteca para trabalhar com rotas na nossa aplicação.

yarn add svero

Para a estrutura de pastas do nosso projeto, primeiro vamos criar a pasta src onde ficará todos nossos componentes. Dentro da pasta src vamos criar os arquivos index.html, main.js, main.css e App.svelte e criar as pastas.

  • assets(pasta que armazena as imagens), dentro do assets criar as pastas img e icons(svg’s)
  • components(pasta com os componentes globais da aplicação), dentro da pasta components criar as pastas common(components genéricos que podem ser utilizados em outras partes do projeto) e custom (componentes customizados para uma necessidade específica)pages(pasta com as páginas da aplicação),
  • services(pastas com os serviços para consgumo da API)
  • pages(pasta com os componentes que serão as páginas de home e details)

Agora iremos escrever nossos arquivos de “entry point”(entrada) que são o index.html, main.js e main.css, como vamos trabalhar com o parcel apontando para o index.html como arquivo principal de entrada, inserir no html os arquivos main.css e main.js.

E agora vamos escrever o main.css, com as dependências do tailwind, para não complicar muito vamos extrair as opções default que o tailwind nos oferece.

E agora o main.js, que será a entrada para o arquivo principal do svelte o App.svelte.

Finalizando a configuração do projeto, vamos criar o postcss.config.js que são as configurações tanto para gerar as classes do tailwind que foram declaradas no nosso main.css e para processar os estilos feitos nos nossos componentes svelte, para isso basta apontar para os arquivos “.html” e “.svelte” da nossa aplicação. Esse arquivo é criado na raiz da pasta do projeto no mesmo nível do package.json.

Para executar o projeto, no package.json dentro da propriedade “scripts” vamos criar duas opções:

  • Dev para executar o projeto enquanto desenvolvemos
  • Build para gerar o arquivos finais para deploy da aplicação
“scripts”: {
“dev”: “parcel src/index.html”,
“build”: “parcel build — no-source-maps src/index.html”,
“test”: “echo \”Error: no test specified\” && exit 1"
},
Estrutura do projeto

Estrutura da Aplicação

A aplicação terá um layout bem simples, com um Header, Main com o conteúdo da aplicação e um Footer, e terá uma página incial e uma de detalhes.
Pela simplicidade optei por utilizar o css grid mesmo o flexbox tendo um suporte maior, o sistema de grid é bem robusto e mais organizado. O roteamento será feito no nosso main, que fica no App.svelte. Para fazer a função de roteamento utilizaremos o svero, que é a biblioteca escolhida para trabalhar com rotas.

Estrutura do App.svelte

<div class="grid-box"><!-- Container da App -->
<header>App header</header>
<main>
<Router>
<!--
conteúdo da aplicação com a utilização das rotas
-->
</Router>
</main>
<footer>App footer</footer>
</div>

Os nossos arquivos de página, ou melhor componentes, ficaram na pasta pages e lá criaremos a Detail.svelte e a Home.svelte

A estrutura da home terá um componente de search para procura dos pokemons e uma grid com pokemons aleatórios, por uma limitação da API, para fazer a procura é necessário procurar pelo número ou o nome exato do pokemon. Para isso vamos fazer uma service que faz a procura do pokemon pelo nome ou número. Na pasta src/services vamos criar o PokeService.js, para o consumo da API. Optei por utilizar o fetch, mesmo não tendo um suporte bem abrangente em todos os navegadores é nativo do Javascript não necessitando dependências externas para consumo de API’s

Nos serviços temos:

  • getPkmn : Retorno com as informações do pokemon consultado pelo id ou nome completo do pokemon
  • getEvolutions: Retorno com as informações sobre a linha evolutória do pokemon consultado pelo id da evolução
  • getSpecies: Retorno auxiliar que contem o id da linha de evoluções do pokemon consultado pelo id do pokemon

Página Home

Na home(pages/Home.svelte) vamos utilizar dois recursos do svelte, um é o “await block”, em que podemos exibir conteúdos pelo estado de uma promise, ou seja enquanto uma promise não é resolvida exibimos um conteúdo como um loader, por exemplo e quando for resolvida exibimos os resultados na página e tem até um bloco para tratamento dos erros. Este é um recurso bem interessante e vamos explorar bastante na nossa aplicação.

<script>
let promise = getPromise();
async function getPromise() {
const result = await httpRequest();
return Promise.resolve(result);
}
</script>
<div>
{#await promise}
<p>Loading …</p>
{:then result}
<p>{ result }</p>
{:catch error}
<p>
Ocorreu um erro ao consultar a API: {error}
</p>
{/await}
</div>

E o outro é o “each block”, que utilizaremos para iterar os resultados da consulta a API, já que é retornado um array de objetos com as informações dos pokemon como nome, imagens, tipos, id, e exibiremos na tela através de um card, o each é um recurso bem comum nos frameworks front-end e aqui não tem muitos mistérios.

PS: temos alguns componentes que serão explicados mais para frente como o Card e o Search que são utilizados na home.

Página de detalhes

Na página de detalhes(pages/Detail.svelte) teremos um card com a imagem de frente e verso do pokemon com nome, uma pequena descrição, tipo e por fim, a linha de evolução. Neste componente utilizaremos também os recursos do await e each block. Para exibir a linha evolutória teremos um componente especial para isso e utilizaremos outros serviços.

Vamos finalizar por aqui e na parte 2 do artigos iremos conhecer os componentes desenvolvidos e finalizar o projeto.

Parte 2 do artigo

--

--