Olá Habr!
Era uma vez, lançamos um
projeto piloto
na pilha MEAN (Mongo, Express, Angular, Node), que geralmente não nos decepcionou, no entanto, decidimos não fazer impressões e atualizações adicionais na época - ao contrário de Manning, que
atualizou este livro . No entanto, continuamos pesquisando nessa direção e hoje gostaríamos de conversar com você sobre a pilha MERN relacionada, onde o React está localizado no cliente, não no Angular. A
palavra é dada a
Tim Smith .

Aviso: todo o código deste artigo está
aqui .
Neste guia de pilha MERN, escreveremos um blog simples usando React.js, Node.js, Express.js e MongoDB para expandir nosso arsenal de pilha completa.
O que é uma pilha?
Talvez a primeira coisa a discutir seja a idéia de uma "pilha" como tal. Existem muitas pilhas diferentes e todas são apenas caminhos diferentes para alcançar o mesmo objetivo. Ao criar um aplicativo de pilha completa, fornecemos a parte do cliente com a qual o usuário interagirá, e a mesma parte do cliente mediará o trabalho com o servidor e o banco de dados - tornando todo esse processo o mais simples e gerenciável possível.
Podemos dizer que a pilha é um determinado conjunto de tecnologias usadas para resolver esse problema.
Embora existam muitas pilhas que valem a pena ser discutidas, algumas delas são mais populares do que outras atualmente. Uma dessas pilhas populares é chamada MEAN e consiste em:
- M ongoDb
- E xpress.js
- A ngular.js
- N ode.js
Hoje falaremos sobre a pilha MERN, que é muito semelhante à MEAN, exceto que Angular.js é substituído aqui por React.js. Assim, podemos usar o MongoDB como um banco de dados, Node.js e Express, respectivamente, para o servidor e roteamento, e React.js - para criar a parte do cliente com a qual o usuário irá interagir.
Como é feito o desenvolvimento com essa pilha?
Antes de passar para todas as sutilezas, vamos dar uma olhada geral em como todos esses elementos funcionam juntos. Pessoalmente, demorei um pouco para entrar nisso, pois minha formação está relacionada ao PHP, onde as partes do cliente e do servidor estão um pouco confusas.
1. A parte do servidor (Node e Express.js) e a parte do cliente (React.js)Primeiro de tudo, você precisa entender que a parte do servidor e a parte do cliente são entidades separadas. A parte do cliente pode estar no mesmo repositório do servidor ou talvez em um completamente diferente.
2. Terminais API são usados para comunicaçãoSe você já está pensando em como fazer amizade com as partes do cliente e do servidor, responderei: isso é feito através da API. Uma API (interface do programa de aplicativo) é criada no servidor, onde obteremos "terminais" pelos quais o aplicativo localizado na parte do cliente pode interagir com o servidor.
Vamos explicar com os dedos: imagine que sua mão esquerda é do lado do servidor e sua mão direita é do lado do cliente.
Agora dobre as mãos e torça os dedos como se estivesse apertando a própria mão. É assim que as linguagens de modelos funcionam. Eles permitem que você exiba algumas marcações junto com os dados despejados nos servidores - e neles os componentes do cliente e do servidor se sobrepõem em grande parte.
Agora abra suas mãos. Afaste os dedos o máximo possível e faça as mãos esquerda e direita tocarem apenas com as pontas dos dedos. É assim que a pilha MERN funciona. A parte do servidor fornece terminais (pontas dos dedos da mão esquerda) para acesso ao servidor, para o qual o cliente envia chamadas (pelas pontas dos dedos da mão direita) e através desses pontos de contato, troca informações com o servidor (mão esquerda).
Espero que tenha ficado um pouco mais claro e, se não, esqueça toda essa metáfora, como se eu não a tivesse mencionado.
Nosso servidor Node.js e Express.js
Embora eu não dê instruções passo a passo sobre como criar essa pilha aqui (este é um tópico para um artigo separado), gostaria de considerar os vários elementos da pilha que geralmente são usados ou podem ser usados nela. Eu mesmo li vários manuais que informavam como configurar o servidor, mas não explicava por que essas bibliotecas específicas são usadas para isso.
Depois de criarmos o arquivo app.js, você precisará instalar vários pacotes. A seguir, estão os pacotes mais comuns que eu já usei em meus projetos com o Express.js - talvez também sejam úteis para você.
- O Express.js é uma estrutura para criar aplicativos da web. Possui funcionalidade interna para resolver muitos problemas, em particular, para estabelecer roteamento.
- O Mongoose é um gerenciador de dados do objeto (ODM) que fornece interoperabilidade entre um aplicativo express.js e um banco de dados do MongoDB.
- BodyParser é uma biblioteca que permite que o aplicativo express.js leia o corpo (ou seja, o conteúdo) das solicitações recebidas.
- DotENV - permite usar arquivos com a extensão .env para trabalhar com dados confidenciais.
- Passport.js - fornece autenticação em nosso aplicativo e fornece vários métodos de autenticação diferentes.
- Validador - validação simples de muitos tipos de dados
- bCrypt - criptografia de dados confidenciais, como senhas
- Nodemon - "reinicialização a quente" para o servidor do nó, caso a situação mude; Graças ao Nodemon, você não pode parar ou reiniciar o servidor após fazer as alterações.
Obviamente, existem muitos outros pacotes, mas, na minha experiência, são essas bibliotecas que são usadas com mais frequência.
Então, depois de classificar alguns dos pacotes mais usados, vejamos o código. Para começar - nosso servidor:

Este é um servidor API simples. Como você pode ver, ele é equipado com a funcionalidade básica CRUD (Criar-Ler-Atualizar-Excluir) - nada sobrenatural. Uma análise mais detalhada mostrará que
res.json()
é usado aqui para fornecer dados de saída para uma URL específica - ou seja, HTML ou outro modelo não é usado para saída. É assim que criamos nossas APIs, abrindo o acesso aos dados no React.js.
Você também pode notar que eu apenas apontei o mangusto para o meu próprio servidor mongodb instalado no meu computador. Para que esse mecanismo funcione corretamente, o MongoDB deve estar instalado no seu computador e funcionar. Se não funcionar, basta abrir a janela do console e digite o seguinte comando:

Ele iniciará o servidor MongoDB na sua máquina local. Como tudo isso é feito localmente, você não poderá ver minhas postagens se executar o código no repositório. Temos que escrever novos conteúdos. Se você precisar de um esboço de conteúdo, recomendo o excelente gerador
Fillerama.io ,
cortando texto de alguns dos meus filmes e programas de TV favoritos.
Se você estiver interessado em testar o servidor, poderá iniciá-lo com o seguinte comando:

Após o servidor inicializar e nos informar que funciona na porta 3333, além de estar conectado ao MongoDB, você pode abrir o
Postman e testar nossas rotas lá. Quanto às opções GET, você pode simplesmente inserir a rota e clicar em "Enviar". No caso do POST, você terá que selecionar "Corpo" e preencher os campos para o cabeçalho e o conteúdo principal.
Nota do lado do cliente
Agora que configuramos e lançamos nosso servidor, podemos começar a trabalhar no cliente com o qual nossos usuários irão interagir. O cliente será escrito em React.js, e isso pode ser feito de várias maneiras diferentes.
A primeira é simplesmente adicionar todas as bibliotecas necessárias para o lado do cliente (reagir, reagir, reagir roteador etc.), tudo no mesmo arquivo
package.json
em que escrevemos as bibliotecas do servidor. Neste projeto, fiz exatamente isso, mas devo dizer que não acho que essa opção seja ótima. Penso que, à medida que o nosso projeto cresce, a base de código se torna cada vez mais confusa e, se você usar apenas esse método, trabalhar com ele se tornará mais complicado no futuro. Eu preferi esse caminho no aplicativo descrito precisamente porque tenho certeza: ele não crescerá e nem mudará. Este aplicativo foi escrito apenas para fins de demonstração.
A segunda e (na minha opinião) abordagem mais ideal é criar um repositório separado para o lado do servidor e outro para o cliente. Ainda podemos clonar o repositório de peças do cliente no diretório com nosso projeto sem problemas, apenas certifique-se de que a peça do cliente esteja listada em nosso arquivo
.gitignore
. Por exemplo, na estrutura de arquivos deste aplicativo, há um diretório do
client
, onde todo o código da peça do cliente está localizado. Poderíamos levá-lo para um repositório completamente separado e, em seguida, simplesmente adicionar a seguinte entrada ao arquivo
.gitignore
do nosso repositório no lado do servidor:

Ao adicionar a pasta do
client
ao arquivo
.gitignore
, garantimos que o sistema não perceberá essa pasta como o segundo repositório no projeto. Além disso, essa abordagem facilita o trabalho de redesenhar ou substituir a parte do cliente, pois a parte do servidor não é afetada.
A decisão de como exatamente seu aplicativo de pilha cheia será projetado depende inteiramente de você. Parece-me que, se você mantiver repositórios separados para as partes do cliente e do servidor, a estrutura do aplicativo será um pouco mais precisa.
Criamos uma parte do cliente no React.js
Agora, tendo entendido a organização do projeto, vamos falar, na verdade, sobre o código do cliente. Abaixo está o meu arquivo
app.js
para um aplicativo no React.js, e não inserirei código para cada componente neste post, apenas deixo um
link para o repositório e explico o que cada um dos componentes do React faz.
E aqui está a aparência da captura de tela da página principal do nosso aplicativo:

Como você pode ver, o
app.js
nada complicado. Existe um <Router> que permite configurar rotas no React.js que exibem vários componentes com base em seus URLs. Aqui estão os outros componentes que serão usados em nosso aplicativo React.js:
- Cabeçalho - A barra de navegação localizada na parte superior da tela
- Índice - lista as entradas de blog disponíveis
- Novo - O formulário através do qual o usuário pode criar uma nova postagem
- Único - exibe uma entrada de blog específica com base em seu
id
- Editar - O formulário através do qual o usuário pode atualizar a entrada do blog encontrada pelo
id
Usamos o Axios para fazer chamadas http para os terminais da API e, em seguida, usamos o React.js para exibir os dados como desejamos. Nesta postagem, fornecerei o código Index.js para tornar mais claro como tudo funciona juntos.

No código acima, um componente de classe está envolvido, permitindo o uso de métodos de estado e ciclo de vida. Isso é necessário porque as chamadas do Axios devem ser feitas no método do ciclo de vida
componentDidMount()
. Observe que eu estava recebendo um erro de CORS ao tentar fazer chamadas para minha API local. Para resolver esse problema, adicionei vários cabeçalhos ao arquivo server.js no meu servidor Express - e funcionou. Esse código é observado nos comentários no arquivo server.js.
Vamos garantir que os robôs de pesquisa leiam nosso aplicativo React.js normalmente.Para finalizar, gostaria de falar brevemente sobre a renderização. Se você iniciar o site e acessar diretamente alguma postagem do blog, poderá haver alguns problemas com a exibição do conteúdo. Nesse caso, a navegação no site será inconveniente não apenas para os usuários, mas também para pesquisar robôs que indexam conteúdo. Para contornar esse problema, recomendo o uso de ferramentas como Gatsby js ou Next js. Essas duas soluções são diferentes umas das outras, mas ambas podem ser úteis, dependendo do que exatamente você precisa.
Gatsby js é um gerador de site estático. Você pode escrever um site no React.js e o Gatsby o transformará em arquivos estáticos durante a compilação, o que tornará o site super rápido. O Gatsby vem com muitos plugins úteis que tornam a ferramenta quase universal. A propósito, meu site foi criado com o Gatsby.js! Como os arquivos estáticos são criados durante a montagem, o site precisa ser reconstruído sempre que o conteúdo original for alterado.
O Next.js , por sua vez, é um componente do servidor para exibir sites React.js. Muitos recursos úteis são incorporados a ele, em particular roteamento, divisão de código, componentes projetados e muito mais. A renderização do servidor significa que os dados serão atualizados automaticamente, como são feitos no servidor, mas, antes de serem exibidos na janela do navegador, o estágio de renderização ocorrerá. É por isso que não deve haver problemas com a exibição de dados para o usuário, e os robôs de pesquisa também farão seu trabalho sem problemas.
Existem muitas outras soluções desse tipo, mas eu ouvi mais sobre essas duas e, ao trabalhar nesse projeto, as usei. Ambos são excelentemente documentados, por isso é fácil lidar rapidamente com os dois e começar a trabalhar.
Considerações finais sobre a pilha MERN
Esperamos que este artigo tenha ajudado um pouco mais precisamente como a pilha MERN funciona. Nele, pegamos o MongoDB, Express.js e Node.js e criamos a partir deles um servidor que já fornece terminais de API através dos quais nosso aplicativo React.js pode acessar dados. Então agora que você entende muito, é hora de fazer grandes coisas!