AWS Serverless 06: Front End no S3 e CDN com CloudFront
Implante no Amazon S3 a aplicação Front End em React que consome a API de livros, configurando o bucket como site estático, com política de leitura pública e CORS. Depois, distribua o site por uma CDN com o Amazon CloudFront.
1. Visão geral
Neste material, prosseguimos com o desenvolvimento da solução retratada a seguir.

A solução que estamos desenvolvendo.
Lembre-se que temos interesse na seguinte API (coleção de endpoints).
| Endpoint | Finalidade |
|---|---|
POST /livros |
cadastrar um livro novo |
GET /livros |
obter todos os livros |
GET /livros/{id} |
obter um livro pelo seu id |
PUT /livros/{id} |
atualizar um livro pelo seu id |
DELETE /livros/{id} |
apagar um livro pelo seu id |
Neste material, vamos implantar uma versão da aplicação Front End que utiliza apenas os endpoints
GET /livros(obter todos os livros)GET /livros/{id}(obter um livro pelo seu id)
O que você vai aprender
- As principais características do Amazon S3 e suas classes de armazenamento
- Como gerar o build de produção de uma aplicação React
- Como criar um bucket no S3 e configurá-lo como servidor web de conteúdo estático
- Como escrever uma bucket policy de leitura pública e uma configuração de CORS
- Como fazer upload dos arquivos do Front End e acessar o site
- O que é uma CDN e como criar uma distribuição no Amazon CloudFront
O que você vai precisar
- Uma conta na AWS com acesso ao console
- O Back End dos materiais anteriores (API Gateway + Lambda + DynamoDB), de preferência em execução
- Git, Node.js/npm e o VS Code instalados
2. Amazon S3
A implantação do Front End será realizada utilizando-se o AWS S3. Veja algumas características sobre ele.
- Modelo de Dados de Objeto: o S3 armazena dados como objetos dentro de "buckets". Um objeto consiste em dados, um ID exclusivo e metadados.
- Durabilidade e Disponibilidade: o S3 oferece uma durabilidade de 99,999999999% (11 9's) e garante 99,99% de disponibilidade durante um ano.
- Classes de Armazenamento: o S3 oferece várias classes de armazenamento, incluindo STANDARD, INTELLIGENT_TIERING, ONEZONE_IA, GLACIER e GLACIER_DEEP_ARCHIVE. Cada classe tem seu próprio preço e uso recomendado com base na frequência de acesso e no período de retenção dos dados.
Classes de armazenamento
Veja uma descrição sobre as classes de armazenamento.
S3 Standard (STANDARD)
- Uso: projetado para uso geral e armazenamento de dados frequentemente acessados.
- Durabilidade: 99,999999999% (11 9's) ao longo de um ano.
- Disponibilidade: 99,99% ao longo de um ano.
- Recuperação: recuperação em tempo real.
- Custo: geralmente maior do que os demais.
S3 Intelligent-Tiering (INTELLIGENT_TIERING)
- Uso: ideal para dados com padrões de acesso desconhecidos ou que mudam com o tempo.
- Durabilidade: 99,999999999%.
- Disponibilidade: 99,9%.
- Recuperação: em tempo real.
- Custo: taxas de monitoramento e automação são aplicadas, mas geralmente é mais barato do que o STANDARD para dados com padrões de acesso variáveis.
S3 Standard-Infrequent Access (STANDARD_IA)
- Uso: para dados menos acessados, mas que ainda precisam de recuperação rápida quando necessários.
- Durabilidade: 99,999999999%.
- Disponibilidade: 99,9%.
- Recuperação: em tempo real.
- Custo: menor custo de armazenamento por GB em comparação com o STANDARD, mas com taxas de recuperação.
S3 One Zone-Infrequent Access (ONEZONE_IA)
- Uso: para dados que podem ser recriados e são acessados com menos frequência, mas que ainda precisam de recuperação rápida.
- Durabilidade: 99,999999999%, mas armazenados em apenas uma zona de disponibilidade, portanto, menos resiliência a falhas em comparação com outras classes.
- Disponibilidade: 99,5%.
- Recuperação: em tempo real.
- Custo: menor do que o STANDARD_IA, pois utiliza apenas uma zona.
S3 Glacier (GLACIER)
- Uso: arquivamento de dados de longo prazo que podem tolerar tempo de recuperação de algumas horas.
- Durabilidade: 99,999999999%.
- Disponibilidade: não é imediata; a recuperação leva de alguns minutos a várias horas.
- Recuperação: de minutos a horas, dependendo do nível de recuperação escolhido.
- Custo: muito mais baixo do que classes de armazenamento em tempo real, mas com taxas de recuperação.
S3 Glacier Deep Archive (GLACIER_DEEP_ARCHIVE)
- Uso: arquivamento de dados de longo prazo que são acessados muito raramente.
- Durabilidade: 99,999999999%.
- Disponibilidade: não é imediata; a recuperação leva cerca de 12 horas.
- Recuperação: em torno de 12 horas.
- Custo: a classe de armazenamento mais barata no S3, mas com taxas de recuperação.
Estas classes permitem que os usuários otimizem custos, mantendo a durabilidade e disponibilidade necessárias para seus dados. Ao escolher uma classe de armazenamento, é importante considerar a frequência de acesso, o tempo de retenção desejado e o orçamento disponível.
Outros recursos
- Modelo de Segurança: você pode controlar o acesso aos buckets e objetos usando a AWS Identity and Access Management (IAM), controlar o acesso público e usar políticas de bucket. Além disso, oferece recursos de criptografia para proteger os dados em trânsito e em repouso.
- Transfer Acceleration: esta funcionalidade usa a rede global da Amazon CloudFront para acelerar os uploads e downloads de objetos para e do S3. Como veremos, funciona como um CDN.
- Versionamento: permite preservar, recuperar e restaurar todas as versões de todos os objetos em um bucket. Isso é útil para recuperação de desastres e histórico.
- Eventos: é possível configurar notificações para serem acionadas em resposta a determinados eventos no S3, como a criação ou exclusão de objetos.
- Replicação: você pode configurar a replicação automática e assíncrona de objetos para um bucket diferente, potencialmente em uma região AWS diferente.
- Hospedagem de Sites Estáticos: os buckets do S3 podem ser configurados para hospedar sites estáticos sem a necessidade de servidores web tradicionais.
3. Obtendo a aplicação Front End
A aplicação Front se encontra no seguinte repositório no Github
https://github.com/professorbossini/pessoal_react_aws_livros
Crie uma pasta vazia para você e vincule o VS Code a ela clicando em File >> Open Folder. Depois disso, abra um terminal interno dele com Terminal >> New Terminal. No terminal, use
Terminal
git clone https://github.com/professorbossini/pessoal_react_aws_livros.git .
para clonar o repositório. Para testar a aplicação localmente, comece baixando as dependências com
Terminal
npm install
E execute com
Terminal
npm start
Observe que a aplicação já "vem" com uma URL de Back End fixa. A ideia é que você possa encaixar a sua URL ali para testar o seu Back End. Clique em Obter todos para visualizar a lista de livros atual.

A aplicação exibindo a lista de livros depois de clicar em Obter todos.
Gerando o build
Uma aplicação React executa puramente no Front End. Observe como, em ambiente de desenvolvimento, ela possui uma estrutura própria para esse ambiente.

A estrutura do projeto em ambiente de desenvolvimento.
Ocorre que o navegador apenas "entende" HTML, CSS, Javascript e arquivos de recursos como áudio, vídeo etc. Assim, quando a aplicação está pronta para ser implantada, executamos um script que produz esse conteúdo em função daquilo que foi desenvolvido. No caso de uma aplicação React, o comando é
Terminal
npm run build
Observe como este comando criou uma pasta chamada build.

A pasta build gerada pelo comando.
Esta coleção de arquivos é a nossa aplicação Front End. Agora vamos configurar um ambiente no AWS S3 para fazer a sua implantação. Como você verá, será tão simples quanto copiar e colar todos esses arquivos.
4. Configurando um bucket no S3
A fim de implantar a aplicação, vamos criar um Bucket no S3. Um Bucket pode ser utilizado para armazenar arquivos e também pode ser configurado para operar como um servidor web de conteúdo estático.
Na página inicial do S3, clique em Create bucket.

A página inicial do Amazon S3.
Comece escolhendo um nome para o seu Bucket.

O nome do bucket.
Ajuste as configurações de permissão de acesso como a seguir. Em particular, quando desmarcamos Block all public access, estamos permitindo que o bucket seja acessado externamente. Entretanto, também precisaremos dizer explicitamente como o seu conteúdo pode ser acessado (talvez em modo de leitura ou modo de escrita).

ACLs desabilitadas, Block all public access desmarcado e o aviso reconhecido.
Mantenha as demais opções com seu valor padrão e clique em Create bucket.

Criando o bucket.
Habilitando o site estático
Na tela resultante, clique no nome do seu bucket para ajustar as suas configurações.

Abra o seu bucket.
No momento, nosso bucket apenas serve para armazenar arquivos. Ele ainda não opera como um servidor Web estático. Vamos ajustar isso. Comece clicando em Properties.

A aba Properties.
Role a página até encontrar a opção Static website hosting e clique em Edit.

Editando a hospedagem de site estático.
Marque a opção Enable. Preencha o campo Index document com index.html (esse é o nome do arquivo inicial gerado quando fizemos o build da nossa aplicação) e clique em Save changes.

Habilitando o site estático com index.html como documento inicial.
5. Política de acesso e CORS
No próximo passo, vamos configurar permissões de acesso aos objetos dentro do Bucket. Veja um trecho da documentação a esse respeito.
Bucket policies
"With Amazon S3 bucket policies, you can secure access to objects in your buckets, so that only users with the appropriate permissions can access them. You can even prevent authenticated users without the appropriate permissions from accessing your Amazon S3 resources."
Leia mais em
https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html
Neste exemplo, vamos dizer que todos os objetos do bucket têm acesso "somente leitura". Clique em Permissions.

A aba Permissions.
Encontre o campo Bucket policy e clique em Edit.

Editando a bucket policy.
Agora adicione o seguinte conteúdo.
Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::livros-pdfs/*"
}
]
}
Veja uma explicação para cada chave deste objeto JSON que define a policy.
- Version: versão da linguagem de política que estamos utilizando. É importante pois, ao longo do tempo, novas versões podem ser liberadas e seu funcionamento pode ser diferente.
- Statement: fica associado a uma coleção de declarações. Cada declaração é um objeto que caracteriza uma permissão.
- Sid: significa Statement Id e é opcional. É uma espécie de rótulo que pode te ajudar a lembrar sobre a razão de ser deste statement.
- Effect: especifica se este objeto define permissão ou negação de acesso. Os valores possíveis são
allowedeny. - Principal: especifica quais usuários estão envolvidos nesta declaração. O asterisco indica todos, autenticados ou não.
- Action: ação para a qual a permissão está sendo especificada. Valores possíveis são:
s3:CreateBucket,s3:DeleteBucket,s3:GetObject,s3:DeleteObject. E assim por diante. Observe que temos ações envolvendo o bucket e ações que envolvem objetos dentro do bucket. - Resource: qual recurso está envolvido nesta declaração. ARN vem de Amazon Resource Name e a notação
arn:aws:s3:::é um padrão Amazon para identificar recursos do S3.
Quando terminar, clique em Save changes.
CORS
A seguir, role a página e encontre a opção para configuração de CORS. Clique em Edit.

Editando a configuração de CORS.
Use o seguinte objeto JSON para liberar o acesso sem restrições.
Configuração de CORS
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedOrigins": ["*"]
}
]
Veja uma explicação para cada chave neste objeto JSON. Em qualquer caso, o asterisco simboliza "tudo".
- AllowedHeaders: quais cabeçalhos podem estar presentes na requisição. Valores possíveis são "Authentication", "Content-type" e assim por diante.
- AllowedMethods: quais métodos do protocolo HTTP podem ser usados.
- AllowedOrigins: a partir de quais origens requisições podem ser atendidas. Lembrando que uma origem é caracterizada pelo protocolo, host e porta.
Clique em Save changes.
6. Upload dos arquivos e teste
Para fazer o upload dos arquivos da sua aplicação, volte à aba Objects. Observe que o campo inferior permite que você arraste e solte arquivos.

A área de upload da aba Objects.
Arraste e solte os arquivos da sua pasta build. Não arraste a pasta, apenas o seu conteúdo.

Arraste o conteúdo da pasta build, não a pasta.
Observe que o ambiente mostra a lista de arquivos que vai fazer parte do upload. Clique em Upload.

Os arquivos que farão parte do upload.
Quando terminar, clique em Close.

Upload concluído.
Clique na aba Properties novamente. Agora vamos encontrar o link do nosso app.

Volte à aba Properties.
Role a página até encontrá-lo. Geralmente é uma das últimas opções.

O endereço do site estático em Bucket website endpoint.
Visite o link no seu navegador e veja se deu tudo certo.

A aplicação servida pelo S3.
Se o Back End estiver em execução, deve ser possível obter a lista completa de livros.

Obtendo todos os livros.

Obtendo um livro pelo id.
7. CDN com AWS CloudFront
CDN (Content Delivery Network)
Coleção de servidores espalhados geograficamente responsáveis por entregar ao cliente determinado conteúdo.
A ideia é que todos os servidores sejam capazes de entregar o mesmo conteúdo e que o usuário final seja atendido pelo servidor que estiver mais próximo dele geograficamente, o que tende a diminuir a latência (tempo de espera entre a requisição e a resposta). Veja uma figura. A ideia que ela passa é que há diferentes grupos de usuários em diferentes regiões. Cada grupo é atendido por um servidor do CloudFront diferente. Observe que há também outros recursos que podem ser usados, como um Firewall e Caching.

Como o CloudFront entrega conteúdo a usuários de diferentes regiões.
Veja algumas vantagens que o AWS CloudFront traz.
- Desempenho: tempo de latência reduzido, pela possibilidade de um dos servidores estar mais próximo do usuário final.
- Redundância e disponibilidade: como existem muitos servidores, a falha de um não compromete o funcionamento do sistema como um todo.
- Distribuição de carga: como existem muitos servidores, nenhum deles fica sobrecarregado.
- Atualização e manutenção de conteúdo: quando o conteúdo a ser entregue ao usuário final tiver de ser atualizado, o desenvolvedor pode fazê-lo em um único ponto. O AWS CloudFront possui um mecanismo de "invalidação", que instrui os servidores a obterem nova cópia atualizada junto à origem do recurso.
É comum que serviços de streaming, como o Netflix e o Amazon Prime, utilizem serviços de CDN. Frameworks CSS, como o Bootstrap, também costumam ser disponibilizados por meio de uma CDN.
8. Criando uma distribuição no CloudFront
Para utilizar o AWS CloudFront, vamos criar uma distribuição. Trata-se de uma coleção de configurações em que especificamos a origem dos recursos (o bucket S3 neste caso) e outras coisas, como questões de segurança e outras funcionalidades oferecidas por ele. Comece visitando a sua página no console.
Comece clicando em Create distribution. Talvez a sua tela seja um pouco diferente mas você deverá ver esta opção.

Criando uma distribuição.
Clique no campo Origin domain e escolha seu bucket S3.

Escolha o bucket S3 como origem.
Caso ela apareça, clique para utilizar a recomendação da Amazon, que sugere que utilizemos a URL do site e não aquela direta do bucket S3.

Use o endpoint do site em vez do endereço direto do bucket.
Há algumas razões técnicas sutis para isso sobre as quais não falaremos no momento.
Vá rolando a página. Quando chegar em Allowed HTTP methods, faça os seguintes ajustes: escolha GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE e, em Cache HTTP methods, marque OPTIONS.

Métodos HTTP permitidos e cache do método OPTIONS.
Role um pouco mais a página e escolha não utilizar o WAF. Ele tem um preço alto e não o utilizaremos no momento.

Não habilite o WAF.
Observe que você pode escolher regiões do mundo onde deseja ter servidores do CloudFront. Mantenha as opções com seu valor padrão e clique em Create distribution.

Em Price class você escolhe as regiões atendidas; mantenha o padrão.
Na tela a seguir você já terá acesso a uma URL para acesso ao seu site por meio do CloudFront. Seu status deverá ser deploying. Pode demorar alguns minutos até que o conteúdo fique acessível.

A URL da distribuição e o status Deploying.
Aguarde alguns minutos e faça um teste no seu navegador.

A aplicação servida pelo CloudFront.
9. Exercícios
A aplicação a seguir foi implementada com Flutter.
https://github.com/professorbossini/pessoal_flutter_aws_livros.git
Faça deploy dela no S3.
Para fazer build, você pode executar
Terminal
flutter build webEntretanto, pode ser o caso de seu ambiente não ter o flutter instalado. Por esta razão, o repositório já inclui o build para web pronto. Encontre-o na pasta
build.Crie uma distribuição para seu app usando o AWS CloudFront.
Faça novo deploy no S3, depois de atualizar a URL de Back End padrão, utilizando a sua. Se você tiver o ambiente flutter disponível e puder fazer novo build, ajuste a URL no código fonte da aplicação e faça novo build. Caso contrário, nos arquivos de build, encontre onde fica a URL de Back End e troque lá mesmo.
10. Encerramento
Parabéns! Você publicou o Front End da API de livros como um site estático no Amazon S3, com política de leitura pública e CORS, e o distribuiu mundialmente por meio de uma CDN com o Amazon CloudFront.
Referências
- Amazon Web Services (AWS) - Cloud Computing Services. 2023. Disponível em https://aws.amazon.com/. Acesso em setembro de 2023.
- PiCloud Launches Serverless Computing Platform To The Public | TechCrunch. 2023. Disponível em https://techcrunch.com/2010/07/19/picloud-launches-serverless-computing-platform-to-the-public/. Acesso em setembro de 2023.
- Serverless Architectures. 2023. Disponível em https://martinfowler.com/articles/serverless.html. Acesso em setembro de 2023.
- Who coined the term 'serverless'?. 2023. Disponível em https://www.quora.com/Who-coined-the-term-serverless. Acesso em setembro de 2023.