O que é Template Engine?
Olá leitor, seja muito bem vindo a mais uma lição da jornada do NodeJS 🥳
Aqui, nós iremos mergulhar no conceito dos famosos Templates Engines do NodeJS.
Será por meio deles que daremos mais vida a nossa aplicação, onde seremos capazes de criar e carregar páginas HTML, que contenham uma lógica embutida.
Sem mais delongas e spoilers, vamos direto ao nosso conteúdo 😌
Como inserir conteúdos dinâmicamente no HTML das nossas páginas?
Antes de mergulhamos no assunto, você se lembra que durante a lição anterior, você aprendeu a carregar arquivos HTML
, usando apenas o seu servidor com Express
?
Naquela lição, nós vimos como fazer isso por meio de duas formas diferentes:
- Carregando um arquivo
.html
existente dentro da pasta do projeto. - Enviando estruturas HTML (famoso HTML inline) que existiam dentro de variáveis, de volta ao cliente.
Como se tratavam de conteúdos estáticos, ou seja, que não possuem dados e informações que são alterados dinâmicamente.
O conteúdo da lição passada foi de grande valia, pois no final das contas, conseguimos atender os resultados esperados, que no nosso caso, foi a distribuição de conteúdo HTML na resposta do servidor.
Mas como eu faria para servir conteúdo dinâmicamente de acordo com os dados que estão armazenados no meu servidor?
Por exemplo: Como eu faria para carregar uma lista de nomes que existe dentro de um objeto/array, dentro um template HTML?
Pensando em uma solução rápida, há duas formas de se fazer isso 🤓
Usando HTML Inline) Dentro da variável que representa o conteúdo HTML (inline), você poderia concatenar a sua lista de nomes dentro da própria variável, por exemplo:
// Armazena os nomes em um array
const nomes = ['João', 'Maria', 'Carlos', 'Ana', 'Paulo'];
// Cria a variável com o HTML inline completo
let htmlInline = `
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lista de Nomes</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
h1 {
color: #333;
}
ul {
background-color: #fff;
padding: 10px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
li {
padding: 5px 0;
}
</style>
</head>
<body>
<h1>Lista de Nomes</h1>
<ul>`;
// Adiciona os nomes dentro da lista
nomes.forEach(nome => {
htmlInline += `<li>${nome}</li>`;
});
htmlInline += `
</ul>
</body>
</html>`;
// Exibe o HTML resultante no console (ou pode ser injetado em uma página)
console.log(htmlInline);
Solicitando Requisições HTTP) Após servir o conteúdo HTML
de volta ao seu cliente (navegador do usuário), você poderia criar um script em Javascript, que fizesse uma solicitação a uma das rotas do seu servidor, de modo a retornar um array com a lista de nomes.
E usando puramente Javascript, você poderia modificar o DOM da sua página, de modo a atualizar a lista de forma dinâmica, por exemplo:
// Define a lista de nomes
const nomes = ['João', 'Maria', 'Carlos', 'Ana', 'Paulo'];
// Cria a rota GET que retorna a lista de nomes em formato JSON
app.get('/nomes', (req, res) => {
res.json(nomes);
});
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lista de Nomes</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
h1 {
color: #333;
}
ul {
background-color: #fff;
padding: 10px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
li {
padding: 5px 0;
}
</style>
</head>
<body>
<h1>Lista de Nomes</h1>
<ul id="nomes-lista"></ul>
<script>
// Função para buscar a lista de nomes da API e atualizar o DOM
function carregarNomes() {
fetch('http://localhost:3000/nomes')
.then(response => response.json()) // Converte a resposta para JSON
.then(nomes => {
const lista = document.getElementById('nomes-lista');
// Limpa a lista antes de inserir novos itens
lista.innerHTML = '';
// Insere cada nome na lista
nomes.forEach(nome => {
const li = document.createElement('li');
li.textContent = nome;
lista.appendChild(li);
});
})
.catch(error => {
console.error('Erro ao carregar a lista de nomes:', error);
});
}
// Chama a função ao carregar a página
window.onload = carregarNomes;
</script>
</body>
</html>
Todas as alternativas acima funcionam perfeitamente, mas e se eu te disser que existe uma forma de criar o seu HTML dinâmicamente, inserindo variáveis do back-end diretamente no front-end?
Com isso, você não precisaria fazer o uso do HTML inline, e muito menos realizar solicitações HTTP de volta ao servidor!
Sim, tudo isso é possível com o uso dos Template Engines 🤩
O que é Template Engine?
Um Template Engine (ou motor de template) é uma ferramenta que permite inserir dados dinâmicos em arquivos HTML
de forma eficiente.
É por meio deles, que podemos criar layouts que podem ser reaproveitados pelas diferentes partes da nossa aplicação.
Ele funciona como um intermediário entre o servidor (onde os dados são gerados) e o HTML
em sí (onde os dados são exibidos).
Ou seja, com ele nós podemos substituir variáveis dentro dos templates (arquivos HTML) por dados reais que estão armzenados no nosso servidor, onde tudo isso é feito antes que o HTML
seja enviado ao cliente.
Por de baixo dos panos, é como aplicar a técnica do HTML
inline, só que dentro de um arquivo .html
, conseguiu entender? 🧐
Ainda não? Então veremos como esse conceito se comporta na prática 😉
Como funciona um Template Engine?
Imagina que na pasta do seu projeto, você tem um template em HTML
chamado de index.html
.
Dentro dele, existem códigos (feitos com Javascript) responsáveis por capturar todos os dados que chegam até esse template.
Com esses dados em mãos, o template conta com marcações especiais, onde os dados dinâmicos serão inseridos dentro dessas marcações (<%= nome %>), por exemplo:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Usuários</title>
</head>
<body>
<h1>Lista de Usuários</h1>
<ul>
<% users.forEach(user => { %>
<li><%= user.name %></li>
<% }) %>
</ul>
</body>
</html>
Já no servidor, você define os dados que devem ser passados para o template, e isso pode ser feito da seguinte forma:
const dadosQueSeraoEnviados = ['Micilini', 'Roll', ....];
carregar('index.html', dadosQueSeraoEnviados);
É como se o template fosse uma espécie de função do Javascript, na qual recebe e trata os parâmetros que chegam até lá (variáveis temporárias).
Quando a função fictícia "carregar
" é executada, por de baixo dos panos, a lógica do template engine processa o template (abre o arquivo HTML), e substitui as marcações com os valores fornecidos (dadosQueSeraoEnviados
), tudo isso para gerar um HTML
final.
Por fim, o servidor então envia o HTML
renderizado de volta ao cliente.
Repetindo: É como se o template fosse uma espécie de função do Javascript, na qual recebe e trata os parâmetros que chegam até lá (variáveis temporárias), afim de inserir esses dados dentro do HTML, e retornar a versão final com os dados já inseridos.
Incrível, não acha?
Principais vantagens de se usar um Template Engine
O uso dos Template Engines trás consigo uma série de vantagens relacionadas ao nosso projeto, onde podemos citar algumas:
Separação de lógica e apresentação: o código de backend fica separado da visualização (HTML), o que respeita o princípio da separação de responsábilidades.
Reutilização de templates: facilita o uso de layouts e componentes reutilizáveis, por outras partes da sua aplicação (rotas).
Manutenção facilitada: mantem o código mais simples, uma vez que a lógica de renderização está concentrada em cada um dos templates.
Dinamismo: permite criar páginas web de forma dinâmica, que respondem a diferentes dados e condições.
Dito isso, os Templates Engines representam uma maneira poderosa de gerar HTML
dinâmico em aplicações feitas com NodeJS, permitindo que os desenvolvedores se concentrem em gerar conteúdo baseado em dados, enquanto mantêm o HTML
separado da lógica da aplicação.
Sendo assim, o que é HTML
fica junto de tudo o que está relacionado a Layout, e o que é lógica da aplicação fica dentro de outras pastas.
Quais são os Templates Engines mais utilizados do mercado?
Um Template Engine, nada mais é do que uma biblioteca que não faz parte dos Core Modules do NodeJS.
Sendo assim, já é de se imaginar que existam varios pacotes que podem nos atender 🙃
Veremos cada um deles abaixo...
EJS (Embedded Javascript Templates)
Considerado o mais famoso de todos os tempos, ela permite a inserção de código JavaScript diretamente dentro do HTML
, facilitando a manipulação de dados.
A grande maioria das aplicações em NodeJS fazem o uso da biblioteca EJS
devido a sua simplicidade.
A sua sintaxe é bem simples, visando combinar HTML
com JavaScript por meio das das tags <%= %>
para exibir variáveis, e <% %>
para lógica de controle (loops, condições), por exemplo:
<ul>
<% users.forEach(user => { %>
<li><%= user.name %></li>
<% }) %>
</ul>
Pug (anteriormente chamado de Jade)
É uma Template Engine que usa uma sintaxe simplificada, sem a necessidade do desenvolvedor fazer o uso de tags HTML
de forma explícita.
O que economiza espaço, tornando o código mais legível para os desenvolvedores.
É importante ressaltar que a curva de aprendizado do Pug
é maior se comparado a outras bibliotecas de Template Engine.
Sobre a sua sintaxe, ela usa a indentação para definir a hierarquia dos elementos, atuando de forma similar ao Python.
ul
each user in users
li= user.name
HandleBars
Baseado em Mustache, o HandleBars
é um Template Engine declarativo que não permite a execução da lógica dentro dos templates (como loops ou condições diretamente).
Isso promove uma separação clara entre o que é arquivo de lógica, e o que é arquivo de layout (apresentação). O que vai de acordo com a estrutura MVC
, que aprenderemos em lições futuras 🙂
Essa biblioteca faz o uso de chaves duplas {{ }}
para expressões, promovendo uma clareza maior no seu código.
<ul>
{{#each users}}
<li>{{name}}</li>
{{/each}}
</ul>
Vale a pena fazer o uso dos Templates Engines?
Atualmente, existe uma grande separação no mundo do desenvolvimento web, em que diz que o NodeJS deve ser usado para aplicações back-end, enquanto aplicações front-end devem ser feitas por meio de outras bibliotecas (tais como ReactJS, Angular, Vue e afins)...
Recentemente, eu publiquei um artigo no Portal da Micilini, que fala sobre as diferenças entre Aplicações Monolíticas e Aplicações Modulares.
A verdade, é que existe uma grande movimentação no mercado de TI, em que se dá mais ênfase na construção de Aplicações Modulares, em que o front-end é totalmente separado do back-end, do que seguir pelo modelo antigo (Aplicações Monolíticas) em que o front-end e back-end coexistem no mesmo projeto.
O uso dos Templates Engines no NodeJS, por sí só, faz com que sigamos na construção de Aplicações Monolíticas.
E não há nada de errado com isso, ok?
Você pode sim, criar o seu back-end junto com front-end no NodeJS usando Templates Engines 😉
Agora, se vale a pena seguir por esse caminho ou não, vai depender de uma série de outros fatores, que já foram discutidos aqui.
Mas independentemente se vai valer a pena pra você ou não, na próxima lição, nós ainda assim, iremos aprenderemos a criar HTML
dinâmico usando a biblioteca HandleBars 🙂
É verdade que a maioria das aplicações em que o front-end é separado do back-end, vem ganhando cada vez mais espaço no mercado de TI. Hoje em dia, é menos comum encontrarmos vagas de emprego (projetos) que atuam com aplicações monolíticas. Mas tenha em mente que elas ainda existem... E mesmo que você nunca vá criar layouts diretamente com NodeJS, vale a pena aprender como tudo isso é feito. Vai que amanha você precisa disso, não é mesmo? 😅
Conclusão
Nesta lição, você aprendeu mais a fundo sobre o funcionamento de um Template Engine, e como ele pode te ajudar com o seu projeto.
Na próxima lição, veremos o funcionamento da biblioteca HandleBars!
Te aguardo lá 😉