Como fazer deploy de um projeto ReactJS?

Como fazer deploy de um projeto ReactJS?

Olá Leitor, seja bem vindo a terceira lição da jornada onde eu vou te ensinar a como fazer deploy de um projeto feito com ReactJS 😄

"Maaaas já?" "Nem começamos a criar um projeto ainda!"

Exatamente, e diferente da maioria dos cursos e treinamentos que vemos por aí a fora, onde a maioria dos professores só ensinam a fazer o deploy no último módulo. 

Nós aqui da Micilini resolvemos fazer isso de forma diferente, pois sabemos a necessidade (ansiedade) de alguns alunos em quererem descobrir de imediato como publicar um projeto.

Onde muitos deles, não conseguem esperar o fato de ter que aprender tooooodos os conceitos, para então chegar no último módulo e aprender a publicar um projeto.

Não, muitos alunos querem fazer isso durante às aulas, pois sabemos que muitos deles acabam não chegando até o final do curso 😕 

Ou acham que já aprenderam o suficiente para começar a desenvolver suas próprias aplicações 😅

Enfim, chega de papo e vamos direto ao que interessa!

Afinal, você o que é deploy?

O que é Deploy?

No mundo da tecnologia, deploy significa o processo de implantar ou lançar uma aplicação. 

Na lingua dos devs é "colocar uma aplicação no ar" ou "jogar para o ambiente de produção".

Onde os usuários finais poderão acessá-lo da mesma forma como você está acessando este artigo e aprendendo com ele 😆

Antes do portal da Micilini ir ao ar, primeiro eu construí esse projeto na minha máquina local (ambiente local), para só depoooois colocá-lo em um ambiente de produção (fazer o famoso deploy).

O ato de pegar uma aplicação que está sendo executada na sua máquina local e jogá-la para um servidor online (AWS, Hostgator, Digital Ocean...) chama-se DEPLOY.

Fazendo Deploy de uma aplicação em ReactJS

Fazer o deploy de uma aplicação em ReactJS não é tão simples como clicar e arrastar os arquivos para um ambiente de produção, assim como fazemos com o CPanel ou o Filezilla.

Para exemplificar, vamos supor que você abriu uma conta nesses servidores compartilhados da vida. Vamos pegar como exemplo o servidor de hospedagem da hostgator.

Supondo que você seja assinante do plano start:

E que ele esteja executando o sistema operacional Linux.

Provavelmente você terá acesso ao CPanel, onde conseguirá acessar um aplicativo chamado File Manager.

Será por meio desse aplicativo que você poderá subir todos os arquivos que estão na pasta raiz do seu projeto ReactJS, para dentro da pasta public_html ou www do seu servidor:

O problema é que se você fizer isso exatamente da forma como a ilustração abaixo te informa:

Você vai se deparar com uma série de erros assim que acessar o seu domínio, e mesmo que você navegue para a pasta public e tente acessar o index.html, a sua aplicação vai retornar uma tela em branco.

Isso aconteceu porque o seu navegador e nem o seu servidor souberam interpretar o seu projeto feito em ReactJS.

Mas por que será que isso aconteceu?

Simples, um projeto feito com HTML, CSS e Javascript puro é diferente de um projeto feito em ReactJS.

Enquanto na primeira alternativa você já tem o index.html e páginas correlacionadas se conectando a interagindo com os arquivos que existem dentro da pasta assets.

No caso do ReactJS, a estrutura está organizada de forma totalmente diferente:

É por esse motivo que o servidor não tem inteligência o suficiente para dispor de meios para fornecer aquilo que o navegador do cliente precisa para executar o projeto.

Portanto, se você acreditava que o processo de deploy de uma aplicação em ReactJS era tão simples quanto somente segurar e arrastar aquivos, você está completamente enganado 😅

Atualmente existe duas formas de se fazer um deploy com ReactJS:

  • Usando o comando npm run build,
  • Ou Usando o NodeJS.

Veremos o funcionamento de cada um deles a seguir.

Remova o <React.StrictMode> antes de executar o npm run build

Durante a sua jornada de desenvolvimento, você poderá se deparar com mensagens duplicadas mostradas pelo console.log, além de outras mensagens de erros e alertas que o ReactJS poderá te mostrar.

Geralmente isso acontece pois seu projeto está envolvido dentro de uma tag chamada <React.StrictMode>.

Ela está presente dentro do index.js que existe na pasta src:

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
 <React.StrictMode>
 <App />
 </React.StrictMode>
);

O objetivo desta tag é ajudar os desenvolvedores a escrever aplicativos React mais robustos, identificando problemas potenciais e incentivando as melhores práticas.

Só que, em um ambiente de produção (quando o seu projeto já esta no ar) não faz mais sentido manter essa tag, onde muitos desenvolvedores (e até mesmo a própria documentação do ReactJS) recomendam a remoção dela antes de executar um npm run build.

Sendo assim, antes de executar o npm run build certifique-se de que você removeu as tags <React.StrictMode> </React.StrictMode>, fazendo com que seu projeto fique mais ou menos assim:

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
 <App />
);

Lembrando que a Isso remoção desta tag, garante que você esteja testando e implantando uma versão do seu aplicativo que se comporte da mesma forma que em produção.

Agora, vamos entender como funciona o npm run build.

npm run build

O ReactJS conta com uma configuração chamada de npm run build, que deve ser executada na raiz da pasta do seu projeto, e que é responsável por criar uma versão otimizada do aplicativo destinada à implantação em produção.

Resumindo, o npm run build transforma toda aquela estrutura de arquivos e pastas em arquivos puros (HTML, CSS e JS), de modo que no futuro você possa segurar e arrastar esses arquivos para dentro do seu servidor de produção.

O comando npm run build está declarado dentro do arquivo package.json:

E a sua funcionalidade depende exclusivamente das configurações definidas no arquivo package.json do seu projeto, bem como das configurações padrão do ReactJS e das ferramentas que você está utilizando. 

Mas no caso de um projeto padrão feito exclusivamente com ReactJS (como fizemos até agora), ele é responsável por criar uma pasta chamada build dentro da raiz do seu projeto (ou dentro da pasta public em versões anteriores do ReactJS)

Essa pasta build é o local onde ficará armazenado todos os arquivos compilados pelo ReactJS, e que estarão prontos para serem usados no seu servidor 😄

Primeira Tarefa

Dentro do projeto que nós criamos na lição 1 (meuapp), abra o terminal e execute o comando [npm run build] dentro da pasta raiz do seu projeto.

Vamos agora, explorar o conteudo que existe dentro dessa pasta:

Como podemos ver, a maioria dos arquivos que se encontravam na pasta public, agora estão na pasta raiz de build.

Se você abrir o index.html, verá que além dele estar minificado, ele esta implementando o arquivo main.8f764ef4.js que existe dentro da pasta static > js.

<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.8f764ef4.js"></script><link href="/static/css/main.e6c13ad2.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Além disso, o arquivo também implementa main.e6c13ad2.css que se encontra em static > css.

Se tivéssemos criado um aplicativo bem mais complexo, todas as folhas de estilo e camadas de lógica em Javascript, estariam dispostas em arquivos existentes dentro das pastas css e js.

Se abrirmos o arquivo main.8f764ef4.js você verá que toda a lógica da aplicação está minificada e compilada em javascript puro (diga-se de passagem que é um código dificil de se entender a primeira vista).

A mesma coisa acontece com o main.e6c13ad2.css.

Ou seja, no final das contas o comando npm run build compilou, agrupou e minificou todos aqueles arquivos que estavam dentro da pasta src em um punhado de pequenos arquivos mais enxutos 😂

E nesse momento podemos adentrar na seguinte discursão: "Se no final o projeto vai ser convertido em uma versão pura (HTML, CSS e JS) por que não criar aplicações front-end diretamente nessa versão?"

Essa pergunta é equivalente a:

  • Porque escrever em ReactJS se não podemos criar aplicações diretamente com assembly ou código binário?
  • Qual é a vantagem de usar uma máquina de lavar roupa automática em vez de lavar as roupas à mão?
  • Por que usar um micro-ondas para aquecer alimentos rapidamente em vez de usar um fogão convencional?
  • Por que utilizar um serviço de entrega de alimentos online como o Uber Eats ou o iFood, em vez de ir ao restaurante fisicamente?
  • Por que usar um aplicativo de GPS como o Google Maps ou o Waze para navegar, em vez de usar um mapa físico ou pedir direções para alguém?

Pois bem, acredito que você já saiba qual é a resposta rs

Esses exemplos mostram como, em muitos casos, optamos por ferramentas ou tecnologias que simplificam tarefas, economizam tempo e proporcionam uma experiência mais conveniente, mesmo que isso signifique abstrair-se das complexidades mais baixo nível ou tradicionais.

Voltando para o universo do ReactJS, ele pode oferecer benefícios significativos em termos de produtividade, manutenção e escalabilidade do código.

Se você for parar para pensar, é relativamente mais fácil e organizado para NÓS DESENVOLVEDORES criarmos aplicações usando o framework do ReactJS, do que tentarmos fazer isso a moda antiga (usando o puro e simples HTML, CSS e JS).

"Então quer dizer que a cada atualização da minha aplicação eu devo executar um npm run build, e depois fazer deploy?"

Sim! Ao menos que você integre uma politica CI/CD junto ao build da aplicação.

Atenção: Quando for passar os arquivos para dentro do seu servidor de produção (pastas www ou public_html) não se esqueça de passar os arquivos que existem dentro da pasta build e não a pasta build em si, ok?

Usando o NodeJS

Se você já participou da Jornada de NodeJS aqui do Portal da Micilini, você deve ter notado uma certa familiaridade entre os comandos do NodeJS e do ReactJS.

Isso porque, por de baixo dos panos o ReactJS faz o uso do NodeJS para executar a sua aplicação em modo de desenvolvimento.

Mas isso não signfica que o ReactJS depende do NodeJS para funcionar, ok? Quero dizer apenas que o ReactJS usa o npm e NodeJS para instalar dependências e iniciar servidores de desenvolvimento.

Entretando, você pode fazer o uso do NodeJS para rodar a sua aplicação em ReactJS, vejamos o passo a passo:

Passo 1) Certifique-se de ter o Node.js e o npm instalados em sua máquina (ou servidor de produção).

Passo 2) Inicialize um novo projeto Node.js e instale as dependências necessárias, incluindo o React.js e o Express.js (um framework para Node.js que facilita a criação de servidores web):

mkdir meu-projeto
cd meu-projeto
npm init -y
npm install react react-dom express

Passo 3) Crie um diretório para o seu aplicativo React.js e inicialize um novo projeto React dentro dele:

mkdir meu-projeto/react-app
cd meu-projeto/react-app
npx create-react-app .

Passo 4) Crie uma build do seu aplicativo React.js:

npm run build

Passo 5) Volte para o diretório principal do seu projeto e crie um arquivo JavaScript para o servidor Node.js:

cd ..
touch server.js

Passo 6) Abra o arquivo server.js em um editor de texto e adicione o seguinte código para configurar um servidor Node.js com o Express.js para servir a build do seu aplicativo React.js:

const express = require('express');
const path = require('path');

const app = express();

// Servir a build do aplicativo React.js
app.use(express.static(path.join(__dirname, 'react-app/build')));

// Rota para servir o aplicativo React.js
app.get('*', (req, res) => {
 res.sendFile(path.join(__dirname, 'react-app/build', 'index.html'));
});

// Definir a porta do servidor
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
 console.log(`Servidor Node.js executando na porta ${PORT}`);
});

Passo 7) Inicie o servidor Node.js:

node server.js

Tenha em mente que apesar de estamos usando o NodeJS para executar o ReactJS, ainda assim, estamos realizando o build da aplicação, fazendo com que o NodeJS execute os arquivos de uma aplicação que foi compilada.

"Beleza, mas será que existe alguma forma de passar as pastas node_modules, src... para dentro de um servidor de produção, e executar um npm start por lá, da mesma forma como estamos fazendo na máquina local?"

Sim, isso é totalmente possível, entretanto é importante considerar os aspectos de configuração, segurança e manutenção para garantir um funcionamento adequado e seguro do projeto.

Muitas vezes, é mais comum construir uma versão otimizada do aplicativo usando npm run build e implantá-la em um servidor de produção para garantir uma execução mais estável e eficiente 🙂

npm run build e o react-router-dom

Se você estiver usando a biblioteca do react-router-dom (veremos o funcionamento dela em lições futuras), você precisa fazer algumas modificações na pasta public beeem antes de que executar o npm run build.

Para isso, com o seu projeto aberto, vá na pasta public da sua aplicação, e crie um novo arquivo chamado _redirects, com o seguinte conteúdo:

/* /index.html 200

Salve este arquivo, e gere uma nova build por meio do comando npm run build.

Dentro da pasta build o arquivo _redirects já estará lá, e isso significa que o projeto foi compilado com sucesso, bastando apenas que você pegue esse conteúdo e jogue para dentro de um servidor local.

Esse tipo de configuração é necessária e esta na documentação do react-router-dom, executamos esse processo para que a nossa aplicação compilada ainda continue reconhecendo as rotas do seu projeto.

Caso contrário a aplicação compilada terá dificuldade em abrir as rotas da sua aplicação.

Conclusão

Essa jornada do ReactJS está sendo uma jornada e tanto não é mesmo?

Creio que sim, e na próxima lição você vai aprender a criar o seu primeiro componente em ReactJS, te aguardo lá!