O guia definitivo para hospedar uma SPA Angular/React com S3, Route 53 e CloudFront
Tags: angular, react, aws, cloudfront
Published: 2023-03-22 02:28:33

O combo S3 + CloudFront é uma ótima opção para hospedagem de aplicações Angular e React. Como dito antes [nesse post](https://dev.to/aws-builders/deploy-de-angularreact-para-o-s3-via-github-actions-43mn), uma SPA é simplesmente um monte de arquivos HTML, CSS e JS que rodam no browser, então qualquer servidor de arquivos cumpre a responsa de hospedar esse tipo de aplicação.

O S3 (Simple Storage Service) é um serviço de armazenamento de objetos que pode ser usado para armazenar e recuperar qualquer quantidade de dados de qualquer lugar na web.

O CloudFront, por sua vez, é uma rede de entrega de conteúdo (CDN) que entrega dados, vídeos, aplicativos e APIs com segurança, baixa latência e alta velocidade de transferência. Ao usar o CloudFront com o S3, você pode melhorar o desempenho e a confiabilidade do seu site ou aplicativo distribuindo seu conteúdo globalmente para reduzir a latência, melhorar o tempo de carregamento das páginas e a quantidade de acessos ao bucket.

## Pré-requisitos
Antes de começar, precisamos seguir o passo a passo para a  [criação do bucket no S3](https://dev.to/aws-builders/como-criar-e-publicar-uma-aplicacao-angular-no-amazon-s3-49d8), e  caso você queira ter deploys automatizados, [configurar o Github Actions](https://dev.to/aws-builders/deploy-de-angularreact-para-o-s3-via-github-actions-43mn) pra atualizar o bucket automaticamente, Por último, vamos configurar o CloudFront e o Route 53.

> **Importante:** embora uma infinidade de artigos e tutoriais (incluindo o meu anterior) ensine, não é uma boa prática deixar o bucket público em produção. Logo, o CloudFront se torna super necessário, principalmente em ambientes corporativos.


## Reconfigurando o bucket
Depois de seguir o passo a passo do tutorial anterior, vamos tornar o bucket privado novamente. Vá na aba permissions do seu bucket, remova a policy do tutorial anterior e marque a opção **Block all public access**. O resultado deve ser esse:

![Bucket privado e com policy removida](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbmo78nme2iv895mf5oc.png)

## Criando a distribuição
Vá para o [painel do CloudFront](https://console.aws.amazon.com/cloudfront/v3/home) na AWS e clique em **Create Distribution**. Na criação de distribuição, iremos preencher alguns campos:

- **Origin domain:** selecione o bucket com a sua aplicação
- **Origin access:** selecione a opção **Origin access control settings (recommended)**, que irá deixar o bucket acessível somente para o CloudFront.
- **Ainda em Origin Access:** clique em **Create Control Setting**, e em seguida em **create**.
- **Default root object**: preencha `index.html`
- Clique em **Create Distribution**.

Após a criação você verá um aviso dizendo que a policy do bucket precisa ser atualizada. O processo é bem simples: clique em **Copy Policy** no próprio aviso, que irá deixar a policy na sua área de transferência, depois em **Go to S3 bucket**, e cole o conteúdo em Bucket Policy.

![Aviso de que a Bucket Policy precisa ser alterada](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0qitu0z0qt7zn8f01fn.png)

Voltando à sua distribuição do CloudFront, você verá o link onde ela foi publicada. A essa altura o seu app já estará rodando nesse link mesmo com bucket privado.

![Minha distribuição do CloudFront](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6hy1lkycc06xp1o6m2l.png)

## Configuração do domínio
Também é possível configurar um domínio personalizado no Route 53. Caso você ainda não tenha uma zona configurada, você tem duas opções:

- [Configurar o roteamento de DNS para um novo domínio](https://docs.aws.amazon.com/pt_br/Route53/latest/DeveloperGuide/dns-configuring-new-domain.html)
- [Configurar o Route 53 como serviço DNS para um domínio existente](https://docs.aws.amazon.com/pt_br/Route53/latest/DeveloperGuide/MigratingDNS.html)

Com a hosted zone criada, basta navegar até ela e clicar em **Create Record** para criar um novo registro, e setar como **Alias to CloudFront Distribution** e apontar para a URL da sua distribuição como no print abaixo:

![Exemplo de criação de domínio personalizado no Route 53](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yl3bvj6ql0fs43opc7mf.png)

Depois, precisamos voltar no painel do CloudFront > sua distribution > settings e:

- Adicione o seu domínio como **alternate domain name**
- Crie um certificado
  - Clique em **Request certificate**
  - Selecione **Request a public certificate** na janela que vai abrir
  - Insira o seu domínio em **Fully qualified domain name**
  - Clique em Request
  - Na lista de certificados, clique no certificado recém-criado
  - Em Domains, vá em **Create records in Route 53** e confirme a operação
  - Aguarde o certificado ficar com o status **Issued** (pode levar alguns minutos)
- Selecione o certificado que você acabou de criar

![Configuração do CloudFront com o domínio novo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqefbxff0yx9mgp61b66.png)

## O pulo do gato
Tanto o Angular quanto o React possuem o conceito de rota, o que significa que elas são tratadas no frontend. Se o usuário der um F5 ou tentar abrir uma rota diferente do seu app, o CloudFront vai tentar buscar essa rota no S3 e retornar um erro porque ele não vai encontrar nenhum objeto na roda solicitada.

A solução é redirecionar as requests para o `index.html`. Para isso, vá em **Error Pages** > **Create Custom Error Response** e crie a configuração abaixo:

![Custom Error Response configurada como http error = 403, customize error = yes, response page path = /index.html, http response code = 200: OK](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igvubpnfvg229enxc5o0.png)

Essa config redireciona todos os erros 403 para o `index.html` e retorna Http 200 (OK) para o browser. Assim, independente da rota que o usuário acessar, o CloudFront vai retornar o frontend e o próprio frontend é quem vai gerenciar se aquela rota existe ou não, além de realizar os redirecionamentos caso necessário, que é o comportamento correto.

## GG
Agora temos a aplicação publicada, com o bucket seguro e em uma rede de alta disponibilidade que vai acelerar o carregamento independente da localização do usuário.

![Print da página publicada](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5jrefl6uzy2hqahq4co.png)

É isso! E aí, curtiu? Tem alguma dúvida? Se tiver qualquer coisa que eu possa fazer pra tornar esse artigo melhor, se quiser reclamar, elogiar ou sugerir outro artigo, manda ver nos comentários. Feedbacks são sempre super bem vindos.