Separar o back-end e o front-end se tornou a norma no desenvolvimento de aplicativos full-stack. Mas não há muitas opções para hospedar um aplicativo full-stack em um único provedor.

Neste post, veremos passo a passo como implantar um aplicativo JavaScript full-stack usando Node.js e React on Begin with Begin Data. Vamos fazer a bola rolar!

Opções gratuitas para hospedar um aplicativo JavaScript

Um verdadeiro aplicativo full-stack não só cobriria o backend e o frontend, mas também incorporaria a camada de armazenamento de dados. Não há muitas opções que forneçam uma solução gerenciada para todas as três partes.

Existem apenas algumas opções se você quiser testar sua ideia rapidamente sem pagar um centavo. Vercel e Qovery são dois que vêm à mente para lidar com os back-end e front-end.

Se você se identifica como um desenvolvedor front-end que conhece principalmente uma linguagem-JavaScript-configurar um banco de dados e entender todos os aspectos do back-end e da camada de dados pode se tornar opressor muito rápido. Esta é a área onde Begin.com se destaca. Vamos ver por quê.

Iniciar recursos

Como um desenvolvedor de front-end, você deseja escrever as partes de front-end, mas se necessário, você provavelmente poderia se envolver um pouco no back-end se achar que é um território familiar.

Begin fornece abstrações incomparáveis ​​e ultrautilizáveis ​​além dos serviços AWS populares que muitos de nós são medo de configurar e colar, incluindo AWS Lambda e DynamoDB . Você pode ir do código a um URL funcional em 30 segundos-de graça.

Tudo isso torna o Begin muito amigável ao front-end. Como dizem em sua página inicial, “Begin torna absurdamente fácil sem servidor”. Eles também acrescentam: “Sem servidores. Sem configuração. Sem suor. ” Vamos testar essas afirmações.

Como o Architect (arc.codes) está relacionado ao Begin

Begin pode nos fornecer abstrações altamente utilizáveis ​​além do AWS Lambda, mas vem com suas próprias opiniões sobre como usá-lo.

Begin é como uma versão SaaS do Architect . É uma estrutura sem servidor que ajuda a construir aplicativos sem servidor altamente escalonáveis. É código aberto e seus recursos incluem a capacidade de trabalhar localmente.

O arquiteto tem um layout do projeto definido e prescrições sobre como compartilhe código entre funções Lambda. Com essas opiniões, o Architect facilita a implantação, o registro e o monitoramento.

Na próxima etapa, veremos como construir um aplicativo de notícias simples que busca as últimas notícias dos EUA de fontes como CNN, ABC News e The Guardian.

Pré-requisitos

Antes de mergulharmos no código, a seguir estão algumas coisas que você deve saber:

  1. Você está familiarizado com JavaScript, Node.js e React em geral
  2. Você sabe como o AWS Lambda e as funções sem servidor funcionam de maneira mais ampla
  3. Você tem Node.js em execução em sua máquina local e é capaz de executar comandos npm básicos
  4. Você está familiarizado com Git e GitHub

A seguir, veremos como construir o aplicativo de notícias.

Exemplo de aplicativo: últimas notícias dos EUA

A esta altura, você já sabe que nosso objetivo é construir um pequeno aplicativo de notícias que mostre as últimas notícias dos Estados Unidos de várias fontes. Será semelhante ao exemplo abaixo:

Visualização do nosso aplicativo de notícias mais recente

Este aplicativo de exemplo terá duas partes principais: o back-end escrito em Node.js e o front-end em React. Os dados para este aplicativo de notícias serão armazenados em Begin Data , que é uma abstração muito útil além de DynamoDB. É hora de sujar as mãos com algum código agora.

Primeiros passos com Begin

Para começar a usar o Begin, vá para a página inicial, clique no botão Inscreva-se com GitHub e autorize com sua conta GitHub. Begin tem um plano gratuito generoso que acomoda cinco aplicativos gratuitos, então inscreva-se com eles.

Níveis de preços do Begin

Crie um aplicativo Node + React a partir de um exemplo do Begin

Usaremos um exemplo Begin de Node.js e React para começar. Mais tarde, iremos modificá-lo para se tornar nosso aplicativo de notícias dos EUA.

Vá para o aplicativo Begin Node + React example e clique em Deploy para começar , conforme mostrado abaixo:

Begin's Node and React Starter Template no GitHub

Uma vez que já estamos logados, isso nos levará para a seguinte tela:

Criando nosso aplicativo inicial como um repositório GitHub

Você precisará permitir que Begin acesse seu GitHub. Ao clicar no botão Criar aplicativo , o aplicativo Begin será criado como um novo repositório em sua conta GitHub. No meu caso, ele criou este repositório GitHub de código aberto em minha conta.

Isso iniciará o processo de CI/CD e implantará o aplicativo em um URL de início exclusivo, conforme mostrado abaixo:

O processo de CI/CD sendo executado no início

Você precisará aguardar de 2 a 3 minutos para que o processo de construção e implantação seja concluído e, em seguida, você pode visitar o ambiente de preparação de seu novo aplicativo Begin. Tem uma API muito simples, que o React chama para mostrar seu conteúdo.

Depois de algum tempo, os processos de construção e implantação estão concluídos:

Nossos processos de criação e implantação concluídos no teste

Se atingirmos nosso URL de teste, que, no meu caso, era https://whale-ls5-staging.begin.app/ , veremos um aplicativo React básico:

Nosso aplicativo de reação básica em teste

Viva! Nosso aplicativo React básico com um back-end Node.js super simples está instalado e funcionando em Begin.com.

Ele só será implantado na produção quando colocarmos uma nova tag no GitHub. Begin pede que usemos SemVer para lançamentos com Git tags .

Agora vamos prosseguir para a construção de nossa API de notícias que será consumida pelo React.

Substituindo a API fictícia pela API de notícias

Atualmente, temos uma API fictícia para nosso aplicativo de exemplo disponível em /api . Ele simplesmente responde com uma mensagem Hello from your Begin API! . Excluiremos essa API e adicionaremos duas novas APIs GET .

O primeiro estará acessível em /api/news para obter as últimas notícias salvas em Begin Data. O segundo pode ser acessado em /api/fetch-news para buscar as notícias dos feeds RSS das fontes e salvá-las na tabela de dados Begin. Vamos dar uma olhada no código para fazer tudo isso.

Primeiro, clone o repositório em algum lugar de sua máquina para que possa editá-lo e, em seguida, execute npm install para obter todas as dependências. Para construir essas duas novas APIs, vamos primeiro remover a seção http da seção package.json do arquivo arc e torná-la semelhante à abaixo:

"arc": { "app":"react-hello", "estático": { "pasta":"construir", "spa": verdadeiro }
},

Na próxima etapa, excluiremos a pasta api presente na raiz:

 rm-rf api

Se quiser excluí-lo com uma GUI, deixo essa decisão para você.

Adicione o arquivo app.arc

Posteriormente, adicionaremos um arquivo app.arc que define as rotas e a tabela de dados Begin que usaremos para armazenar notícias. O arquivo app.arc se parece com este:

 @ app
reaja-olá @estático
construção de pasta # json api
@http
obter/api/news
get/api/fetch-news @tables
dados scopeID * String dataID ** String ttl TTL

Algumas coisas importantes a serem observadas aqui são:

  1. Estamos definindo dois pontos de extremidade da API GET , /api/news e /api/fetch-news , que mostrarão as notícias e busque as notícias de nossas fontes definidas e salve-as em Begin Data
  2. Definimos uma diretiva @tables que informa ao Begin nós deseja adicionar uma tabela chamada news com um campo time to live (TTL). Descobriremos o uso do campo TTL mais tarde.

Adicione as rotas de API e arquivos relacionados

Para que as rotas de API funcionem corretamente, precisaremos do módulo rss-parser porque buscamos as notícias nos feeds RSS das fontes. Instale-o com:

 npm i--save rss-parser

Em seguida, adicionaremos os dois arquivos para servir os dois endpoints da API na pasta http , conforme abaixo:

Nossa estrutura de arquivos do aplicativo Destacando dois novos arquivos no Pasta HTTP

O primeiro arquivo é index.js na pasta get-api-fetch_news . É aqui que acontece a maioria das coisas interessantes:

 const data=require ('@ begin/data');
Const Parser=require ('rss-parser');
Const parser=new Parser ();
tabela const='notícias'; function formatFeedStories (histórias, fonte) { const MAX_STORIES=10; deixe formattedStories=[]; deixe contar=0; para (história de histórias) { formattedStories.push ({ título: story.title.trim (), url: story.link, data_de_publicada: história.pubData, fonte }); if (contagem===MAX_STORIES-1) { pausa; } contagem ++; } console.log (`Formatted $ {formattedStories.length} estratificado de $ {source}`, formattedStories); return formattedStories;
} getStories função assíncrona (feedUrl, fonte) { tentar { const feed=await parser.parseURL (feedUrl); retornar formatFeedStories (feed.items, fonte); } catch (errar) { const errMessage=`Erro ao analisar feed de notícias para $ {source}`; console.log (errMessage, err); Retorna []; }
} função assíncrona saveNewsFromSources () { const newsSources=[ { feedUrl:'http://rss.cnn.com/rss/edition.rss', fonte:'CNN' }, { feedUrl:'https://abcnews.go.com/abcnews/topstories', fonte:'ABC News' }, { feedUrl:'https://www.theguardian.com/us-news/rss', fonte:'The Guardian' } ] deixe totalStoriesSaved=0; para (newsSource of newsSources) { const stories=await getStories (newsSource.feedUrl, newsSource.source); const savedCount=espera saveNews (histórias); console.log (`Histórias $ {savedCount} salvas de $ {newsSource.source}`); totalStoriesSaved +=savedCount; } return totalStoriesSaved;
} função assíncrona saveNews (histórias) { const storiesToInsert=[]; const ttl=(Date.now ()/1000) + (60 * 60 * 6);//6 horas a partir de agora em segundos para (história de histórias) { chave const=story.url.slice (-50); const newsExists=await data.get ({tabela, chave}); if (! newsExists) { storiesToInsert.push ({table, key, ttl,... story}); } } if (storiesToInsert.length) { aguarde data.set (storiesToInsert); } return storiesToInsert.length;
} exportações.handler=função assíncrona http (req) { tentar { const noOfStoriesSaved=await saveNewsFromSources (); Retorna { statusCode: 200, cabeçalhos: { 'content-type':'application/json; charset=utf8' }, body: JSON.stringify ({message: `$ {noOfStoriesSaved} Notícias coletadas e salvas!`}) } } catch (e) { console.log (`e: $ {e.message}`, e); Retorna { statusCode: 500, cabeçalhos: { 'content-type':'application/json; charset=utf8', }, body: JSON.stringify ({'message': `ocorreu algum erro ao buscar notícias, $ {e.message}`}) } }
}

O principal trabalho pesado do aplicativo está neste arquivo de 100 linhas. Vamos examinar os pontos principais.

Os URLs do feed RSS das fontes de notícias são definidos em saveNewsFromSources . Em nosso caso, estamos usando CNN, ABC News e The Guardian. Para cada uma dessas fontes de notícias, ele obtém as 10 histórias mais recentes na função getStories .

Depois disso, ele salva as histórias na função saveNews . Isso salva as histórias na tabela news com um tempo de vida (TTL) de 6h apenas se ainda não existir. Portanto, as histórias permanecem no banco de dados por no máximo 6 horas e são excluídas automaticamente após a expiração de seu TTL.

Outro ponto a notar aqui é que geramos uma chave única a partir dos últimos 50 caracteres do URL (NB, chaves nos dados iniciais precisam ter no máximo 50 caracteres). Usamos essa mesma chave para verificar se a notícia já existe; se existir, não o salvaremos novamente.

Registramos coisas como as histórias e o número de notícias salvas para nossa própria referência. Também registramos erros caso algum ocorra.

Consequentemente, adicionaremos o outro arquivo index.js na pasta http/get-news-api para buscar as notícias do armazenamento de dados e servi-las como JSON.

 const data=require ('@ begin/data'); escolha de função (obj, atributos=[]) { return Object.entries (obj) .filter (([chave])=> atributos.includes (chave)) .reduce ((obj, [chave, val])=> Object.assign (obj, {[chave]: val}), {});
} exportações.handler=função assíncrona http (req) { const newsStories=await data.get ({table:'news', limit: 20}); deixe storiesToShow=[]; para (newsStory of newsStories) { const pickStory=pick (newsStory, ['título','url','data_publicada','fonte']); if (pickStory.headline) { storiesToShow.push (pickStory); } } const SortedStories=storiesToShow.sort ((a, b)=> nova data (b.published_date)-nova data (a.published_date)); Retorna { cabeçalhos: { 'content-type':'application/json; charset=utf8', 'cache-control':'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0' }, statusCode: 200, corpo: JSON.stringify (SortStories) }
}

Este pequeno arquivo de 30 linhas é bastante direto. Ele consulta Begin Data para obter 20 notícias. Ele seleciona apenas os quatro campos da resposta headline , url , Published_date e source . Ele faz uma classificação rápida com base na data para colocar as notícias mais recentes primeiro e, em seguida, as lojas classificadas são enviadas como JSON. Muito fácil!

Na próxima seção, veremos como o código React e o CSS são alterados para mostrar as últimas 20 notícias que extraímos da tabela de dados Begin.

Chame a API de notícias do React

O aplicativo de exemplo já chama o endpoint /api para renderizar o texto fictício, mas excluímos a API antiga e adicionamos as novas APIs de notícias. Como tal, precisamos alterar o código para chamar nossas APIs e mostrar as últimas notícias no aplicativo React. Vamos alterar o App.js em src da seguinte maneira:

 importar React, {useState, useEffect} de'react';
importar logotipo de'./logo.svg';
import'./App.css'; const App=()=> { const [histórias, setStories]=useState ([]); const [mensagem, setMessage]=useState ('carregando...'); useEffect (()=> { função assíncrona fetchNewsStories () { tentar { esperar (esperar fetch ('/api/fetch-news')). json (); const data=await (await fetch ('/api/news')). json (); setStories (dados) const message=data.length?'':'Nenhuma história encontrada'; setMessage (mensagem); } catch (errar) { console.log (`err: $ {err.message}`, err); setMessage ('não foi possível buscar histórias'); } } fetchNewsStories () }, []); Retorna ( 
logo

Últimas notícias

{mensagem}
{Array.isArray (stories) && stories.map (story=>

{story.headline} -{story.source}

)}
); } exportar aplicativo padrão;

Vamos fazer um resumo rápido do que o aplicativo React está fazendo. Estamos fazendo duas coisas na função fetchNewsStories dentro do useEffect . A primeira é chamar a API para buscar as notícias e gravá-las no armazenamento de dados.

Em seguida, chamamos a API get news e a definimos como stories . A chamada de busca de notícias é idempotente, pois adicionará notícias que não estão no banco de dados com a chave exclusiva.

A variável de array stories é posteriormente repetida com um Map e mostramos o título e a fonte como H3 com um link para a notícia. Mostramos uma mensagem de carregamento enquanto as histórias estão sendo carregadas e, se houver um erro, mostramos uma mensagem não foi possível buscar histórias para os usuários.

Além disso, também removeremos background-color: # 282c34; na linha 12 e color: white na linha 18 de App.css para tornar as notícias mais legíveis.

Podemos testar rapidamente nosso aplicativo localmente com npm start para ver algo como o seguinte:

Visualização do nosso aplicativo de notícias mais recente

Parabéns! Seu aplicativo de notícias mais recente está funcionando. Se quiser experimentar a aparência da API em seu local, você pode clicar em http://localhost: 3333/api/news para ver a resposta JSON da API get news. Se estiver vazio, primeiro acesse a API de busca de notícias em http://localhost: 3333/api/fetch-news para obter as últimas notícias de todas as três fontes.

Precisamos corrigir os testes escritos com fita para que a etapa do teste no passes de implantação. Para fazer isso, na pasta /test , vamos alterar as linhas 17–26 do arquivo api-test.js para ficar assim:

 test ('get/api/news', async t=> { t.plan (1) tentar { let result=await tiny.get ({url: `$ {base}/api/news`}) t.ok (resultado,'Resposta obtida da API', result.body); } catch (errar) { t.fail (errar) } })

Alteramos o caminho da API no teste e simplesmente afirmamos que recebemos uma resposta da API. Não é um ótimo teste, mas nos permite alcançar nosso objetivo de implantar a API.

Agora vamos implantá-lo para começar. Para implantar as alterações, vamos confirmá-las e enviá-las ao GitHub. As alterações do código principal estão disponíveis como solicitação de pull para sua referência; as alterações do código de teste estão em uma solicitação pull diferente.

Implante o aplicativo de notícias no Begin

Abriremos uma solicitação de pull para o aplicativo de notícias. Depois que a solicitação pull for mesclada, ela implantará automaticamente essas mudanças no ambiente de teste, conforme mostrado abaixo:

Mesclando e implantando a solicitação pull uest

Depois disso, se verificarmos o URL de teste, podemos ver o aplicativo funcionando de maneira semelhante ao nosso local. Podemos visitar o teste clicando no link Teste no canto superior esquerdo da página acima.

Se verificarmos a página Dados , podemos ver que os dados de nossas notícias também estão gravados nos Dados iniciais:

Our Data Table in Begin Data

Finally, we will deploy a production release. Click the Deploy to Production button and select a version — I will go with 0.0.1, with a release note of 0.0.1 first release — and click the Ship It! button:

Indicating Our Release Version

Similar to staging, it will take its time to build, and it deploys by provisioning the resources for us:

Building and Deploying Our App to Production

All of these updates are available via the Activity link. After that, we can check how the app looks in production:

Finished App in Production

You can check my app’s production version to see how it works.

Next steps

Begin provides other features, too, like scheduled functions. We could have used a scheduled function in place of the fetch news API that runs every 6h and fills up our news table. That is one of the reasons I used a TTL of 6h.

You can also check out event functions, which can replace a queue for any functionality that needs one. The example depicts an account verification email, which is a great candidate to use a queue, but it is solved very well by an event-based kind of approach.

You might also want to explore more of Begin — for instance, mapping custom domains is another great feature. All in all, Begin provides solid abstractions on top of AWS services without locking you in.

Conclusão

We saw how we can deploy a full-stack JavaScript app on Begin.com using Begin Data to store our data, too. Rather than using two or three services for data, backend, and frontend, we can utilize Begin to host a full application and its data on the same service. I hope you explore more Begin features like scheduled function and customs domains to easily deploy your idea and have it working with less effort.

The post Deploying a full-stack Node.js + React app for free with Begin appeared first on LogRocket Blog.

Source link