Node.js e Express: Utilizando React como sua view engine

Compartilhando seus componentes no lado do servidor!

Eduardo Rabelo
Jul 21, 2018 · 4 min read
Image for post
Image for post
Poderosa combinação para sua template engine! — Créditos da Imagem para Avanthika Meenakshi

Para tudo. E preste atenção na afirmação seguinte: Esse artigo NÃO É sobre React isomórfico, universal, <nova-buzz-word-aqui>, para isso, existem soluções mais robustas como Next.js, Razzle ou GatsbyJS.

O meu caso hoje é o bom e velho template engine da linguagem de servidor que você trabalha. Para minha sorte (ou não), o projeto está em Node.js.

Nosso cenário atual

O projeto gera relatórios estáticos e tem a seguinte estrutura:

  • Está conectado com 4 serviços diferentes
  • Em torno de 8 telas

Estamos satisfeitos com a estruturação e implementação na parte do servidor.

Percebemos algumas inconsistências na parta da interface, que está utilizando EJS, com isso, resolvemos que era um momento adequado para repensar essa parte da aplicação.

Problemas comuns, independente da tecnologia

Ano vai, ano vem, framework vai, framework vem e os problemas de engenharia de interface do usuário são praticamente idênticos. Para citar alguns:

  • HTML diferente, para um mesmo tipo de componente
  • CSS diferente, para um mesmo tipo de componente
  • Modificações para "esse caso especial"
  • Cores, tamanhos de fonte, peso de texto etc
  • Múltiplas implementações de comportamento/interação semelhantes

Eu presenciei isso com CSS e MooTools, e preciso dizer que também vejo isso com CSS-in-JS e React. Isso não é um problema relacionado a tecnologia, é um problema de planejamento e execução.

Sendo sincero, com as duas últimas tecnologias citadas acima, a frequência é bem menor. Desenvolvedores estão mais familiarizados com conceitos como encapsulamento, responsabilidade única etc. Tudo é um reflexo de um material de maior qualidade para educar o uso desses novos frameworks.

Achando uma solução para nosso o contexto

A um tempo atrás, nós investimos em uma estrutura de componentes em React. Está em produção em várias partes da empresa, com boilerplates e scaffolding automatizados para novas equipes/projetos, uma estrutura de SPA/PWA bem robusta.

Mas nós não queríamos reescrever essa aplicação, ela estava funcionando muito bem obrigado. Queríamos reutilizar todo esse investimento em componentes React, apenas na camada da view dessa aplicação.

A primeira idéia que venho em mente foi:

  • É só carregar o React na view do ejs e colocar um container para renderizar a aplicação.

Bem, isso funciona. Mas alguns problemas com isso:

  • Iríamos precisar manter os fragmentos de ejs e React (view, partials, etc)
  • Precisaríamos injetar os dados no HTML da view, para podermos ler no JS
  • Propenso a futuras confusões/erros por causa dessa fragmentação

Colocando React no Express

Ao procurar melhores soluções, acabamos encontrando:

A idéia da biblioteca é resumida em uma frase:

  • Essa é uma view engine para Express que renderiza componentes React no servidor. É retornado marcação estática e não suporta a montagem dessas views-components como componentes no navegador. — express-react-views

Fantástico! Era exatamente isso que estávamos procurando. Toda a lógica e dados corretos, já estavam sendo passados para a view, queríamos mudar a sua sintaxe e reutilizar nossos componentes, de algo como:

<%- include('header'); -%>
<h1>Title</h1>
<p>My page</p>
<%- include('footer'); -%>

Para:

const { Header, Footer, Text } = require('@nosso-styleguide');<Header />
<Text.Heading1>Title</Text.Heading1>
<Text.Base>My page</Text.Base>
<Footer />

A configuração é bem simples, ao iniciar seu servidor Express:

const express = require('express');
const path = require('path');
const { createEngine } = require('express-react-views');
const server = express();

server.set('views', path.resolve('./views'); // [A]
server.set('view engine', 'js'); // [B]
server.engine('js', createEngine()); // [C]
  • // [A]: Aqui estamos definindo o caminho que ''views" serão definidas. Isso irá refletir na utilização das suas rotas.

Por exemplo:

app.get(‘/’, (res, req) => res.render(‘home’, { name: ‘Eduardo’ }));

Em res.render('home', ...você precisa ter um arquivo ./views/home.js para ser enviado como uma view nessa requisição e { name: 'Eduardo' } será passado como props para o seu componente.

  • // [B]: Estamos dizendo ao Express qual será o tipo de view engine vamos usar.
  • // [C]: Essa é a extensão dos arquivos que serão transformados pelo express-react-views, você pode definir qualquer outra extensão, .jsx por exemplo, para diferenciar esses arquivos no seu servidor.

Finalizando

Com essa abordagem, conseguimos:

  • Eliminar ejs completamente da nossa base código
  • Reutilizar nossos componentes já criados em uma aplicação 100% renderizada no servidor
  • Unificar a linguagem e mentalidade sobre criação de views e componentes (no final, tudo é um componente)
  • Remover "mais uma coisa para aprender" no processo de integração de novos desenvolvedores ou pessoas de outra equipe

Ah! Uma coisa importante que vale mencionar:

É isso aí galera, valeu! 👋 🙏

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store