Pular para o conteúdo
murad.guide

Aplicações Web

Capítulo 17

Front e API juntos no local

2 min de leitura 425 palavras 1 gravura

Neste capítulo você vai servir a página do Ateliê e a API na mesma origem. O projeto-fio é o Ateliê Boa Viagem, ateliê digital fictício em Boa Viagem, Recife.

Seu ponto de partida

Use o exemplo 17-fullstack-local do pacote anexo e copie inicio/ para uma pasta de prática fora do original. A raiz do exemplo é a referência completa desta etapa.

Use servidor só em 127.0.0.1 quando o README do exemplo pedir HTTP local. Abrir ou testar não publica nada.

Como praticar

Leia → copie ou digite → mude uma coisa → preveja → salve → recarregue → confira. Restaure cada experiência antes da próxima. Faça as atividades antes de abrir as respostas comentadas.

Arquivos estáticos + API

O servidor entrega index.html em / e JSON em /api/oficinas. O front usa fetch relativo.

Faça na sua cópia

Confira o trecho no contexto do exemplo antes de mudar.

fetch('/api/oficinas').then(r => r.json()).then(render)

Mude uma coisa e preveja

Mostre os nomes numa lista.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

A lista reflete o arquivo.

Se não acontecer

Suba o servidor Node do exemplo, não só http.server do Python.

Front e API

Formulário chama POST

O submit envia JSON. Após 201, recarregue a lista.

Faça na sua cópia

Confira o trecho no contexto do exemplo antes de mudar.

await fetch('/api/oficinas', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ nome })
});

Mude uma coisa e preveja

Limpe o campo após sucesso.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

Lista atualiza sem recarregar a página inteira.

Se não acontecer

Trate !response.ok.

Espírito local first

Não exigimos nuvem paga. Testes e demo rodam na sua máquina. Serviços externos ficam como próximo passo opcional, fora deste capítulo.

Faça na sua cópia

Confira o trecho no contexto do exemplo antes de mudar.

127.0.0.1 → estudo
produção → outra decisão

Mude uma coisa e preveja

Anote a porta usada no README do exemplo.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

Você sabe encerrar o processo.

Se não acontecer

Ctrl+C no terminal do Node.

Atividades

Atividade 1

Por que fetch(‘/api/oficinas’) sem host?

Atividade 2

O que fazer após POST 201?

Atividade 3

Este volume exige conta em nuvem?

Respostas comentadas

Resposta da atividade 1

Mesma origem do documento servido.

Resposta da atividade 2

Atualizar a lista na interface.

Resposta da atividade 3

Não.

O arquivo completo

Referência do exemplo 17-fullstack-local, reproduzida aqui para que você possa conferir sem sair da página.

public/index.html

<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ateliê + API</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<a class="skip" href="#conteudo">Ir para o conteúdo</a>
<header><p><strong>Ateliê Boa Viagem</strong></p></header>
<main id="conteudo">
<h1>Front e API</h1>
<ul id="lista"></ul>
<form id="form">
<label for="nome">Nova oficina</label>
<input id="nome" required>
<button type="submit">Enviar</button>
</form>
<p id="msg" role="status"></p>
</main>
<script src="/app.js"></script>
</body>
</html>

public/app.js

async function carregar() {
  const r = await fetch('/api/oficinas');
  const dados = await r.json();
  const ul = document.getElementById('lista');
  ul.innerHTML = '';
  dados.forEach((o) => {
    const li = document.createElement('li');
    li.textContent = o.nome;
    ul.appendChild(li);
  });
}
document.getElementById('form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const nome = document.getElementById('nome').value.trim();
  const r = await fetch('/api/oficinas', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ nome }),
  });
  const msg = document.getElementById('msg');
  if (!r.ok) { msg.textContent = 'Falha ao salvar'; return; }
  document.getElementById('nome').value = '';
  msg.textContent = 'Salvo';
  carregar();
});
carregar();