Pontos-chave
- Passar do desenvolvimento local para a produção implica lidar com variáveis de ambiente, gestão de erros, gestão de processos e segurança de uma forma que a tua configuração local nunca exigiu.
- A hospedagem gerida do Node.js trata da maior parte da infraestrutura subjacente, para que te possas concentrar no código em vez de teres de configurar manualmente o PM2, o Nginx e os certificados SSL.
- As opções de implementação vão desde configurações de VPS não geridas, em que tratas de tudo sozinho, até plataformas totalmente sem servidor, cada uma com diferentes compromissos em termos de controlo, custo e complexidade.
Conseguir que uma aplicação Node.js funcione no teu portátil é uma coisa. Colocá-la online num servidor a sério, de forma segura e sem que ela falhe assim que os utilizadores reais a acederem, é um desafio completamente diferente.
Há variáveis de ambiente para gerir, questões de segurança a ter em conta, um gestor de processos para manter a aplicação ativa e, ainda, a questão de saber onde a hospedar, para começar. A maioria dos tutoriais ignora completamente tudo isso.
Neste blogue, vou explicar os aspetos práticos da implementação de uma aplicação Node.js, falar dos diferentes locais onde a podes implementar e, depois, criar um pequeno encurtador de URLs do zero e colocá-lo online na Cloudways.
O que realmente importa ao implementar uma aplicação Node.js
Fazer a implementação não é só executar o comando «npm start» noutro computador. Há alguns aspetos práticos que são mais importantes do que as pessoas costumam pensar.
As variáveis de ambiente são a primeira coisa a ter em conta. Qualquer informação sensível ou específica do ambiente, como chaves de API, portas ou URLs de base, não deve ser codificada diretamente no código-fonte. Localmente, essas informações ficam num ficheiro .env. Em produção, a plataforma de alojamento guarda esses valores e passa-os para a aplicação em tempo de execução.
O tratamento de erros é outro exemplo. Um único erro não tratado em produção pode derrubar toda a aplicação para todos os utilizadores ou, pior ainda, divulgar um rastreio de pilha em bruto que expõe detalhes internos. Um middleware básico de tratamento de erros deteta tudo isso e mostra aos utilizadores algo adequado em vez disso.
Depois, há a questão da segurança. As aplicações em tempo real são analisadas por bots praticamente assim que ficam online. Algumas medidas simples fazem toda a diferença: o Helmet para cabeçalhos HTTP adequados, limitação de taxa para que ninguém consiga sobrecarregar uma rota e validação básica de entradas, para que a aplicação não confie simplesmente no que um visitante aleatório digitar.
E, por fim, manter a aplicação a funcionar. Quando fechares o terminal, o `node server.js` encerra com ele, o que obviamente não vai funcionar num servidor em produção. O PM2 é uma forma de tratares disto por ti próprio, mas numa plataforma gerida, esta parte já está resolvida para ti.
Esquece a configuração do servidor — Implementa no Cloudways
A hospedagem Node.js gerida pela Cloudways trata do servidor, da gestão de processos e de toda a infraestrutura de implementação, para que te possas concentrar na própria aplicação.
Onde é que deves mesmo implementar a tua aplicação Node.js
Não há um único local certo para implementar uma aplicação Node.js; depende mesmo de quanto dos aspetos subjacentes te apetece gerir por tua conta.
VPS não gerido — Recebes um servidor «a nu» e tens controlo total sobre tudo o que nele está. Isso também significa que tens de instalar o Node por tua conta, configurar o PM2, configurar o Nginx, tratar do SSL e gerir as atualizações do sistema operativo. Flexibilidade total, mas também responsabilidade total.
Alojamento Node.js gerido — O fornecedor trata do servidor, da gestão de processos e de toda a parte técnica da implementação. Basta forneceres-lhe um repositório Git, escolheres o teu framework e a versão do Node, e a aplicação fica online. Tens muito menos com que te preocupar.
Sem servidor — Em vez de um servidor persistente, o teu código é executado à medida que for necessário, sempre que chega um pedido. É ideal para aplicações com picos de tráfego e pouco tráfego, mas normalmente implica reescrever partes do código para se adaptar a esse modelo.
Neste tutorial, vou usar a hospedagem gerida do Node.js da Cloudways, principalmente porque me permite concentrar-me na aplicação em si, em vez de perder tempo a configurar um servidor do zero.
Como implementar uma aplicação Node.js: um guia prático
Para juntar tudo isto, vou criar um pequeno encurtador de URLs, uma aplicação que pega num URL longo, te dá um URL curto em troca e redireciona para o original sempre que alguém clicar no link curto.
Quando eu terminar, esta aplicação vai estar a funcionar num servidor real, protegida pelas medidas básicas de segurança que mencionei antes, e a obter a sua configuração a partir de variáveis de ambiente, em vez de qualquer coisa codificada de forma rígida.
O que vou usar
- Node.js
- VS Code
- Express, EJS e SQLite
- Helmet, express-rate-limit e nanoid
Passo 1: Configurar o projeto Node.js
Antes de poder escrever qualquer código, preciso de ter o Node.js instalado no meu computador.
Estou a trabalhar no portátil do escritório, que tem restrições de TI, por isso vou descarregar a versão binária independente do Node.js do site nodejs.org, em vez de usar um instalador normal.

Assim que terminar de descarregar, vou descompactá-lo na minha pasta «Downloads».

Abrir a pasta do projeto no Prompt de Comandos
Vou criar uma pasta para este projeto no meu ambiente de trabalho e vou chamá-la simplesmente de node-url-shortener.
Depois, vou abrir o Prompt de Comandos e ir para a pasta do meu projeto:
cd C:\Users\abdulrehman\Desktop\node-url-shortener
Configurar o Prompt de Comando para o executável do Node
O Prompt de Comando não sabe automaticamente onde estão os ficheiros do Node no meu computador, por isso vou indicar-lhe o caminho manualmente com este comando:
set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.18.0-win-x64\node-v24.18.0-win-x64

Para ter a certeza de que está mesmo a funcionar, vou executar:
node -v npm -v
Ambos os comandos mostraram os números das versões, por isso já posso continuar.
Criar o projeto Node.js
Primeiro, vou criar um projeto simples em Node.js:
npm init -y

Depois, vou instalar tudo o que este projeto realmente precisa: o Express para o encaminhamento, o EJS para renderizar o HTML, o better-sqlite3 para uma pequena base de dados baseada em ficheiros, o nanoid para gerar códigos curtos, o dotenv para carregar variáveis de ambiente e o Helmet juntamente com o express-rate-limit para as duas medidas de segurança mais básicas que qualquer aplicação em produção deve ter.
npm install express ejs better-sqlite3 nanoid dotenv helmet express-rate-limit
Passo 2: Criar o encurtador de URLs
Agora vou abrir a pasta do meu projeto no VS Code. Para isso, vou a «Ficheiro» > «Abrir pasta» e seleciono a minha pasta «node-url-shortener».

Pronto, já abri o meu projeto no VS Code, por isso agora é hora de o compilar de vez.
Configurar a base de dados
A primeira coisa que quero fazer é configurar a base de dados para que os links curtos continuem a existir quando a aplicação for reiniciada. Para isso, na raiz da pasta do meu projeto, vou criar uma pasta chamada «db» e, dentro dela, um ficheiro chamado «database.js». Vou colar isto lá dentro:
const path = require('path');
const Database = require('better-sqlite3');
const db = new Database(path.join(__dirname, 'urls.db'));
db.exec(`
CREATE TABLE IF NOT EXISTS urls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT UNIQUE NOT NULL,
original_url TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
module.exports = db;

Isto cria um ficheiro de base de dados SQLite na primeira vez que a aplicação é executada, com uma tabela que contém o URL original, o seu código abreviado e a data em que foi criado.
Adicionar variáveis de ambiente
A seguir, preciso de um sítio para guardar a configuração que não deva ser codificada diretamente no código. Para isso, na raiz do meu projeto, vou criar um novo ficheiro chamado .env e colar o seguinte:
BASE_URL=http://localhost:3000 NODE_ENV=development

O BASE_URL é o que é usado para criar cada link curto. Mais tarde, vou alterá-lo para o URL do Cloudways em produção. O NODE_ENV=development serve por agora, enquanto estou a testar localmente, mas vou alterá-lo para produção no servidor ativo.
Agora, como não quero que nada disto acabe no meu repositório público do GitHub, vou criar mais um ficheiro na raiz do meu projeto chamado .gitignore e colar o seguinte:
node_modules .env db/urls.db

Isto diz ao Git para ignorar estes três sempre que eu fizer um push. O «node_modules», porque são só pacotes descarregados. O «.env», porque tem os meus valores de configuração reais. E o «db/urls.db», porque é o ficheiro da base de dados local, que não deve ser incluído no código.
Configurar o servidor
É aqui que vou criar a aplicação propriamente dita: ela recebe o URL longo, gera um código curto para ele, guarda ambos na base de dados e trata do redirecionamento quando alguém clica no link curto.
Vou criar um ficheiro chamado server.js na raiz do meu projeto e colar isto lá dentro:

require('dotenv').config();
const express = require('express');
const path = require('path');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const { nanoid } = require('nanoid');
const db = require('./db/database');
const app = express();
const PORT = process.env.PORT || 3000;
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(helmet());
app.use(express.urlencoded({ extended: true }));
// Limit the shorten route to 10 requests per minute per IP
const shortenLimiter = rateLimit({
windowMs: 60 * 1000,
max: 10,
message: 'Too many requests, please slow down.',
});
app.get('/', (req, res) => {
res.render('index', { shortUrl: null, error: null });
});
app.post('/shorten', shortenLimiter, (req, res) => {
const { url } = req.body;
try {
new URL(url);
} catch {
return res.render('index', { shortUrl: null, error: 'Please enter a valid URL.' });
}
const code = nanoid(7);
db.prepare('INSERT INTO urls (code, original_url) VALUES (?, ?)').run(code, url);
res.render('index', { shortUrl: `${BASE_URL}/${code}`, error: null });
});
app.get('/:code', (req, res) => {
const row = db.prepare('SELECT original_url FROM urls WHERE code = ?').get(req.params.code);
if (!row) {
return res.status(404).render('not-found');
}
res.redirect(row.original_url);
});
// Basic error handler so users never see a raw stack trace
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send('Something went wrong on our end.');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
O Helmet é aplicado em toda a aplicação, o percurso abreviado está protegido por um limitador de taxa e há um gestor de erros na parte de baixo que garante que os utilizadores nunca tenham de ver um rastreio de pilha se algo correr mal.
Esse ficheiro server.js aponta para um modelo chamado «index» que ainda não existe, por isso, a seguir, vou criar a página de que ele precisa.
Criar a interface do utilizador
Vou criar uma pasta chamada «views» na raiz do meu projeto e, dentro dela, um ficheiro chamado «index.ejs». Vou colar isto lá dentro:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Shorten a URL</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<div class="card">
<h1>Shorten a URL</h1>
<form action="/shorten" method="POST">
<input type="text" name="url" placeholder="Paste a long URL here" required>
<button type="submit">Shorten</button>
</form>
<% if (error) { %>
<p class="error"><%= error %></p>
<% } %>
<% if (shortUrl) { %>
<div class="result">
<p>Here's your short link:</p>
<a href="<%= shortUrl %>" target="_blank"><%= shortUrl %></a>
</div>
<% } %>
</div>
</main>
</body>
</html>

Dentro da mesma pasta «views», vou criar outro ficheiro chamado «not-found.ejs»; é isto que aparece quando alguém acede a um código curto que não existe. Vou colar isto aqui:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Link Not Found</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<div class="card">
<h1>Link Not Found</h1>
<p>That short link doesn't exist, or it may have expired.</p>
<a href="/">Go back</a>
</div>
</main>
</body>
</html>

E, para terminar esta etapa, vou criar uma pasta chamada «public» na raiz do meu projeto e, dentro dela, um ficheiro chamado «style.css». Vou colar isto lá dentro:
* {
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
background: linear-gradient(135deg, #667eea, #764ba2);
margin: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
main {
width: 100%;
max-width: 500px;
}
.card {
background: #ffffff;
border-radius: 12px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}
h1 {
margin-top: 0;
color: #1f2937;
}
form {
display: flex;
gap: 10px;
margin-top: 20px;
}
input {
flex: 1;
padding: 12px 14px;
border: 1px solid #d1d5db;
border-radius: 8px;
font-size: 14px;
}
button {
background: #667eea;
color: #ffffff;
border: none;
padding: 12px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background: #5568d3;
}
.error {
color: #dc2626;
margin-top: 15px;
}
.result {
margin-top: 25px;
padding: 15px;
background: #f3f4f6;
border-radius: 8px;
}
.result a {
color: #667eea;
word-break: break-all;
}

Isto dá ao conjunto um aspeto simples, tipo cartões, nada de mais, só o estilo necessário para que a aplicação não pareça texto simples e sem qualquer estilo.
A testar o que criámos
Pronto, está na hora de testar. Vou adicionar um script de arranque ao meu `package.json` para não ter de ficar sempre a escrever o comando completo do Node:
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
}

Depois, de volta ao Prompt de Comando:
npm start
Vou verificar se funciona abrindo o meu navegador e indo a http://localhost:3000. Vou colar um URL comprido, clicar em «Shorten» e devo receber um link curto em troca. Ao clicar nele, sou redirecionado diretamente para o original.
Está tudo a correr exatamente como eu quero.

Passo 3: Enviar o projeto para o GitHub
Antes de fazer a implementação em qualquer lugar, quero que isto seja enviado para o GitHub primeiro.
Vou dar uma vista de olhos no GitHub e criar um novo repositório chamado node-url-shortener.
Depois, de volta ao Prompt de Comando, vou executar estes comandos um de cada vez para carregar o meu projeto:
git init git add . git commit -m "First commit" git branch -M main git remote add origin https://github.com/abdulrehman293/node-url-shortener git push -u origin main
Agora vou voltar ao meu repositório do GitHub e atualizar a página. E, como era de esperar, todos os meus ficheiros estão carregados, com exceção do .env, do node_modules e do ficheiro da base de dados local.

Passo 4: Implementação no Cloudways
Neste momento, o meu projeto está a funcionar na configuração local e também já foi enviado para o GitHub. Agora vou transferi-lo do ambiente local para um servidor ativo. Para isso, vou usar a hospedagem gerida do Node.js da Cloudways, criada precisamente para implementar projetos como este diretamente a partir de um repositório Git.
No painel da Cloudways, vou clicar em «Node.js» no menu e, depois, clicar em «Lançar agora».

A partir daqui, vou escolher o plano Starter, já que este projeto não precisa de muitos recursos para funcionar.

Agora, no ecrã «Deploy Your Node.js Web App», vou clicar em «Connect Via Git» e iniciar sessão na minha conta do GitHub quando me for pedido.
Assim que iniciar sessão, vou escolher o meu repositório «node-url-shortener» da lista e continuar.

Passo 5: Configurar e colocar em funcionamento
É nesta próxima parte que eu digo à Cloudways como executar o projeto.
Vou escolher o Express como predefinição do framework. Quanto à versão do Node, vou escolher o Node 24 (LTS). Vou deixar o diretório raiz como está por predefinição.

A seguir, vou clicar na opção «Alterar» em «Definições de compilação e saída». Depois, vou definir o «Gestor de pacotes» como «npm» e o «Ficheiro de entrada» como «server.js».

Agora, como o meu ficheiro .env não foi carregado para o GitHub de propósito, tenho de adicionar esses valores manualmente. Vou à secção «Variáveis de ambiente» e clico em «Adicionar». Aqui, posso adicionar as minhas variáveis.
Para o primeiro, vou definir a Chave como NODE_ENV e o Valor como production.
Depois, vou clicar em «+ Adicionar mais» e definir a «Chave» como «BASE_URL». E, quanto ao valor, por agora, vou colocar um valor provisório como «http://placeholder.com», já que ainda não tenho a minha URL temporária do Cloudways. Volto mais tarde para atualizar isto depois da primeira implementação.
Assim que os dois estiverem inseridos, vou clicar em «Guardar».


Assim que tiver preenchido isso, vou clicar em «Implementar agora».
Agora, o Cloudways vai buscar o código do GitHub, instalar as dependências e iniciar a aplicação usando o ficheiro de entrada que eu indiquei.

O momento da verdade
Assim que a implementação aparecer como bem-sucedida, vou copiar o URL temporário do Cloudways na página «Visão geral» da aplicação.

Vou voltar às Variáveis de Ambiente, atualizar a BASE_URL para essa URL e voltar a implementar para que a alteração entre efetivamente em vigor.



Agora, se eu abrir o meu URL temporário do Cloudways no navegador, colar um URL longo e clicar em «Encurtar», recebo um link curto que aponta para o meu domínio ativo do Cloudways. Ao clicar nele, sou direcionado diretamente para o original. (Também podes configurar o Node.js com o PostgreSQL no Cloudways)

Já está tudo pronto, e qualquer link curto que eu criar daqui em diante vai continuar a funcionar enquanto a aplicação estiver a funcionar.
Além disso, lê a nossa comparação detalhada entre o Django e o Node.js.
Conclusão
E assim termina este guia sobre como implementar uma aplicação Node.js. Neste blogue, abordei o que é realmente necessário para passar do desenvolvimento local para um servidor ativo, as variáveis de ambiente, o tratamento de erros, a segurança e como manter a aplicação ativa, e depois mostrei os diferentes locais onde podes efetivamente implementar a aplicação.
Também criei um pequeno encurtador de URLs com uma interface de utilizador funcional, adicionei medidas básicas de segurança para produção e publiquei o projeto finalizado no meu GitHub. Fica à vontade para cloná-lo e reutilizar o código.
E se também quiseres experimentar implementar algo semelhante por conta própria, o nosso Serviço de Alojamento Gerido para Node.js trata exatamente deste tipo de fluxo de trabalho: liga o teu repositório, escolhe a tua estrutura e já estás no ar.
Pronto para implementar o teu próprio projeto Node.js?
Liga o teu repositório Git, escolhe o teu framework e coloca a tua aplicação online na Cloudways em poucos minutos.
P. Preciso de um servidor especial para implementar uma aplicação Node.js?
Na verdade, não. Um VPS simples serve se te sentires à vontade para gerir o servidor sozinho, ou podes optar por uma plataforma gerida como a Cloudways, onde o servidor, a gestão de processos e toda a parte técnica da implementação são tratados por ti. O «serverless» é uma terceira opção, embora tenda a adequar-se melhor a certos tipos de aplicações do que a outros.
P. Qual é a diferença entre executar uma aplicação Node.js localmente e em produção?
A nível local, és o único utilizador, as falhas não são grande problema e a configuração fica num ficheiro no teu computador. Em produção, há utilizadores reais a usar a aplicação, um único erro não tratado pode derrubar tudo e a configuração tem de ficar fora do código para que ambientes diferentes possam usar valores diferentes.
P. Preciso do PM2 para manter a minha aplicação Node.js a funcionar?
Só se estiveres a gerir o servidor sozinho. O PM2 reinicia a aplicação se esta falhar e mantém-na a funcionar depois de fechares o terminal. Numa plataforma gerida, isso já é tratado nos bastidores.
P. É seguro implementar uma aplicação Node.js diretamente a partir do GitHub?
Sim, desde que tudo o que for confidencial esteja nas variáveis de ambiente e não no código. O teu ficheiro .env deve ser excluído através do .gitignore para que nunca vá parar ao repositório, e a plataforma de implementação armazena esses mesmos valores separadamente e passa-os em tempo de execução.
Start Growing with Cloudways Today.
Our Clients Love us because we never compromise on these
Abdul Rehman
O Abdul é um profissional de marketing experiente em tecnologia, movido a café e criativo, que adora manter-se a par das últimas actualizações de software e gadgets tecnológicos. É também um escritor técnico competente que consegue explicar conceitos complexos de forma simples para um público alargado. Abdul gosta de partilhar os seus conhecimentos sobre a indústria da nuvem através de manuais de utilizador, documentação e publicações em blogues.