Introdução
O mundo digital está sempre em evolução. Hoje, os usuários esperam experiências rápidas e confiáveis em qualquer dispositivo. É aqui que entram as Progressive Web Apps (PWAs), uma tecnologia que combina o melhor dos sites e dos aplicativos móveis.
Imagine um site que funciona mesmo sem internet, envia notificações como um app e carrega quase instantaneamente. Essa é a promessa das PWAs, uma solução que está transformando a web moderna.
Neste guia completo, você vai aprender a criar sua própria PWA do zero. Não se preocupe se você é iniciante! Vamos explicar cada conceito de forma simples e prática, com exemplos reais que você pode seguir.
O que são Progressive Web Apps?
As Progressive Web Apps são sites que oferecem uma experiência semelhante à de aplicativos nativos. O termo foi criado em 2015 por Alex Russell e Frances Berriman para descrever sites que aproveitam as novas funcionalidades dos navegadores modernos.
Uma PWA não é um tipo específico de tecnologia, mas sim uma abordagem de desenvolvimento que segue certos princípios. Diferente dos apps tradicionais, as PWAs não precisam ser baixadas de lojas como Google Play ou App Store.
Principais características das PWAs
As PWAs possuem três características fundamentais:
- Confiáveis: Carregam rapidamente e funcionam mesmo com conexão instável ou sem internet
- Rápidas: Respondem aos comandos do usuário de forma instantânea e suave
- Envolventes: Oferecem uma experiência semelhante à de um aplicativo nativo
Benefícios para usuários e desenvolvedores
Para os usuários, as PWAs trazem:
- Economia de espaço no dispositivo
- Uso reduzido de dados
- Acesso mesmo offline
- Atualizações automáticas
- Interface amigável e familiar
Para os desenvolvedores, as vantagens são:
- Desenvolvimento mais rápido e barato
- Manutenção unificada (um só código para web e dispositivos móveis)
- Maior alcance de usuários
- Melhor taxa de conversão e engajamento
Por que criar uma PWA?
Antes de mergulharmos na parte técnica, vamos entender por que as PWAs estão ganhando tanto espaço no mercado.
O Magazine Luiza, por exemplo, viu um aumento de 84% nas vendas depois de lançar sua PWA. A AliExpress conseguiu dobrar o tempo de permanência dos usuários no site. Esses números mostram o potencial dessa tecnologia.
Quando uma PWA é a escolha certa
Uma PWA pode ser a solução ideal quando:
- Seu público usa diversos dispositivos para acessar seu conteúdo
- Você quer oferecer funcionalidades de app nativo sem o custo de desenvolvimento separado
- A velocidade de carregamento é crucial para seu negócio
- Seu público está em regiões com conexão instável
- Você quer melhorar as taxas de conversão e engajamento
Requisitos técnicos e ferramentas
Para criar uma PWA, você vai precisar de alguns conhecimentos básicos e ferramentas específicas. Não se assuste! Vamos explicar tudo passo a passo.
Conhecimentos básicos necessários
Para acompanhar este guia, é útil ter familiaridade com:
- HTML (para estruturar o conteúdo)
- CSS (para estilizar a interface)
- JavaScript (para programar funcionalidades)
Não precisa ser especialista! Conhecimentos básicos já são suficientes para começar.
Ferramentas essenciais
Para desenvolver sua PWA, você vai precisar de:
- Editor de código: Visual Studio Code (gratuito e fácil de usar)
- Navegador moderno: Chrome ou Firefox (para testar sua PWA)
- Chrome DevTools: Ferramenta integrada ao Chrome para testes
- Node.js: Ambiente para executar JavaScript fora do navegador
- npm ou yarn: Gerenciadores de pacotes para instalar bibliotecas
Todas essas ferramentas são gratuitas e fáceis de instalar, mesmo para iniciantes.
Passo 1: Criando a estrutura básica do projeto
Vamos começar criando a estrutura de arquivos do nosso projeto. Abra seu terminal e crie uma pasta para seu projeto:
mkdir minha-primeira-pwa
cd minha-primeira-pwa
Agora, crie os arquivos básicos:
touch index.html
touch styles.css
touch app.js
Configurando o arquivo HTML
Abra o arquivo index.html
no seu editor e adicione a estrutura básica:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#4285f4">
<title>Minha Primeira PWA</title>
<link rel="stylesheet" href="styles.css">
<link rel="manifest" href="manifest.json">
<link rel="icon" href="images/icon-192x192.png">
</head>
<body>
<header>
<h1>Minha Primeira PWA</h1>
</header>
<main>
<p>Bem-vindo à minha primeira Progressive Web App!</p>
<button id="instalar">Instalar App</button>
</main>
<script src="app.js"></script>
</body>
</html>
Note que incluímos uma referência ao arquivo manifest.json
, que ainda vamos criar. Também adicionamos a meta tag theme-color
, que define a cor da barra de status quando o site é visualizado em dispositivos móveis.
Passo 2: Criando o arquivo de manifesto
O arquivo de manifesto é um componente essencial para uma PWA. Ele é um arquivo JSON que fornece informações sobre seu aplicativo para o navegador, como nome, ícones e cores.
Crie um arquivo chamado manifest.json
na raiz do seu projeto:
touch manifest.json
Adicione o seguinte conteúdo:
{
"name": "Minha Primeira PWA",
"short_name": "PWA",
"start_url": "index.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#4285f4",
"orientation": "portrait",
"icons": [
{
"src": "images/icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "images/icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
Vamos entender cada item deste arquivo:
- name: Nome completo do seu aplicativo
- short_name: Versão curta do nome (para ícones)
- start_url: Página que abre quando o usuário inicia o app
- display: Como o app deve ser exibido (standalone remove a barra de navegação)
- background_color: Cor de fundo durante o carregamento
- theme_color: Cor principal do tema do aplicativo
- orientation: Orientação preferida (retrato ou paisagem)
- icons: Lista de ícones em diferentes tamanhos
Criando os ícones para sua PWA
Agora você precisa criar os ícones para sua PWA. Crie uma pasta chamada images
e adicione seus ícones:
mkdir images
Você pode criar seus próprios ícones ou usar ferramentas como Favicon Generator para gerar os ícones nos tamanhos necessários. Os tamanhos mais importantes são 192×192 e 512×512 pixels.
Passo 3: Implementando o Service Worker
O Service Worker é o coração de uma PWA. Ele é um script JavaScript que funciona como um intermediário entre o navegador e a rede, permitindo funcionalidades como trabalhar offline e enviar notificações.
Crie um arquivo chamado service-worker.js
na raiz do seu projeto:
touch service-worker.js
Adicione o seguinte código:
const CACHE_NAME = 'pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/styles.css',
'/app.js',
'/images/icon-192x192.png',
'/images/icon-512x512.png'
];
// Instalação do Service Worker
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Cache aberto');
return cache.addAll(urlsToCache);
})
);
});
// Ativação do Service Worker
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
// Interceptação de requisições
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// Retorna o recurso do cache se estiver disponível
if (response) {
return response;
}
// Se não estiver no cache, busca na rede
return fetch(event.request)
.then(response => {
// Verifica se a resposta é válida
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// Clona a resposta para armazenar no cache
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache);
});
return response;
});
})
);
});
Este código faz três coisas importantes:
- Instala o Service Worker e armazena em cache os arquivos essenciais
- Ativa o Service Worker e limpa caches antigos
- Intercepta requisições para servir recursos do cache quando offline
Registrando o Service Worker
Agora, precisamos registrar o Service Worker no nosso arquivo app.js
:
// Verifica se o navegador suporta Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registrado com sucesso:', registration.scope);
})
.catch(error => {
console.log('Falha ao registrar o Service Worker:', error);
});
});
}
// Lógica para mostrar o botão de instalação
let installPrompt;
const btnInstalar = document.getElementById('instalar');
btnInstalar.style.display = 'none';
window.addEventListener('beforeinstallprompt', (e) => {
// Previne o comportamento padrão
e.preventDefault();
// Guarda o evento para usar depois
installPrompt = e;
// Mostra o botão de instalação
btnInstalar.style.display = 'block';
});
btnInstalar.addEventListener('click', () => {
// Mostra o prompt de instalação
installPrompt.prompt();
// Espera o usuário responder ao prompt
installPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('Usuário aceitou a instalação');
btnInstalar.style.display = 'none';
} else {
console.log('Usuário recusou a instalação');
}
installPrompt = null;
});
});
Este código verifica se o navegador suporta Service Workers e, em caso positivo, registra nosso service-worker.js
. Também adiciona a lógica para mostrar um botão de instalação quando o app pode ser instalado no dispositivo.
Passo 4: Adicionando estilos básicos
Vamos adicionar alguns estilos básicos para nossa PWA no arquivo styles.css
:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
header {
background-color: #4285f4;
color: white;
padding: 20px;
text-align: center;
border-radius: 5px;
margin-bottom: 20px;
}
main {
background-color: #f9f9f9;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
button {
background-color: #4285f4;
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-top: 15px;
}
button:hover {
background-color: #3367d6;
}
Estes estilos básicos dão uma aparência mais agradável para nossa PWA.
Passo 5: Testando sua PWA localmente
Agora que criamos todos os componentes essenciais, vamos testar nossa PWA localmente. Como o Service Worker só funciona com HTTPS ou localhost, precisamos de um servidor local.
Uma maneira simples de criar um servidor local é usar o pacote http-server
do Node.js:
npm install -g http-server
http-server
Isso iniciará um servidor na porta 8080. Abra seu navegador e acesse http://localhost:8080
. Você deverá ver sua PWA funcionando.
Verificando se sua PWA está configurada corretamente
Para verificar se sua PWA está configurada corretamente:
- Abra o Chrome DevTools (F12 ou Ctrl+Shift+I)
- Vá para a aba “Application”
- No painel esquerdo, verifique:
- “Manifest” (deve mostrar as informações do seu manifesto)
- “Service Workers” (deve mostrar seu Service Worker ativo)
- “Cache Storage” (deve mostrar seus recursos em cache)
Se tudo estiver correto, você verá um ícone de download na barra de endereço do Chrome, indicando que sua PWA pode ser instalada.
Passo 6: Adicionando recursos avançados
Agora que temos uma PWA básica funcionando, vamos adicionar alguns recursos avançados para torná-la mais útil e envolvente.
Implementando notificações push
As notificações push permitem que você envie mensagens aos usuários mesmo quando eles não estão usando seu aplicativo. Vamos adicionar suporte básico para notificações:
Adicione o seguinte código ao seu arquivo app.js
:
// Solicita permissão para enviar notificações
function solicitarPermissaoNotificacao() {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
console.log('Permissão de notificação concedida!');
// Aqui você poderia registrar o usuário em um serviço de push
}
});
}
// Adiciona um botão para solicitar permissão
const btnNotificacao = document.createElement('button');
btnNotificacao.textContent = 'Ativar notificações';
btnNotificacao.addEventListener('click', solicitarPermissaoNotificacao);
document.querySelector('main').appendChild(btnNotificacao);
// Função para mostrar uma notificação de exemplo
function mostrarNotificacao() {
if (Notification.permission === 'granted') {
navigator.serviceWorker.ready.then(registration => {
registration.showNotification('Olá da sua PWA!', {
body: 'Esta é uma notificação de exemplo',
icon: '/images/icon-192x192.png',
vibrate: [200, 100, 200]
});
});
}
}
// Adiciona um botão para mostrar uma notificação
const btnMostrarNotificacao = document.createElement('button');
btnMostrarNotificacao.textContent = 'Mostrar notificação';
btnMostrarNotificacao.style.marginLeft = '10px';
btnMostrarNotificacao.addEventListener('click', mostrarNotificacao);
document.querySelector('main').appendChild(btnMostrarNotificacao);
Adicionando sincronização em segundo plano
A sincronização em segundo plano permite que sua PWA sincronize dados mesmo quando o usuário não está usando ativamente o aplicativo. Adicione este código ao seu Service Worker:
// No arquivo service-worker.js
self.addEventListener('sync', event => {
if (event.tag === 'sincronizar-dados') {
event.waitUntil(sincronizarDados());
}
});
function sincronizarDados() {
return fetch('/api/sincronizar')
.then(response => {
console.log('Dados sincronizados com sucesso');
})
.catch(error => {
console.log('Erro ao sincronizar dados', error);
});
}
E no arquivo app.js
:
// Registra uma tarefa de sincronização
function registrarSincronizacao() {
navigator.serviceWorker.ready
.then(registration => {
return registration.sync.register('sincronizar-dados');
})
.then(() => {
console.log('Sincronização registrada');
})
.catch(() => {
console.log('Sincronização em segundo plano não suportada');
});
}
// Adiciona um botão para testar a sincronização
const btnSincronizar = document.createElement('button');
btnSincronizar.textContent = 'Sincronizar dados';
btnSincronizar.style.display = 'block';
btnSincronizar.style.marginTop = '10px';
btnSincronizar.addEventListener('click', registrarSincronizacao);
document.querySelector('main').appendChild(btnSincronizar);
Passo 7: Otimizando o desempenho
Para uma PWA realmente eficiente, precisamos otimizar o desempenho. Aqui estão algumas técnicas importantes:
Carregamento otimizado de recursos
Modifique seu Service Worker para implementar estratégias de cache mais avançadas:
// No service-worker.js, modifique o event listener 'fetch'
self.addEventListener('fetch', event => {
// Estratégia Cache First para arquivos estáticos
if (event.request.url.match(/\.(css|js|png|jpg|jpeg|svg|gif)$/)) {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request).then(fetchResponse => {
return caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
});
});
})
);
} else {
// Estratégia Network First para conteúdo dinâmico
event.respondWith(
fetch(event.request).catch(() => {
return caches.match(event.request);
})
);
}
});
Esta abordagem usa duas estratégias diferentes:
- Cache First para recursos estáticos (CSS, JS, imagens)
- Network First para conteúdo dinâmico
Economizando dados e bateria
Para economizar dados e bateria, adicione estas configurações ao seu arquivo app.js
:
// Detecta quando o dispositivo está com bateria fraca
navigator.getBattery().then(battery => {
battery.addEventListener('levelchange', () => {
if (battery.level <= 0.15) {
console.log('Bateria fraca, economizando recursos');
// Aqui você pode desativar funcionalidades não essenciais
}
});
});
// Detecta quando o usuário está com conexão limitada
if ('connection' in navigator) {
const connection = navigator.connection;
connection.addEventListener('change', () => {
if (connection.saveData || connection.effectiveType === 'slow-2g') {
console.log('Modo de economia de dados ativo');
// Aqui você pode carregar versões mais leves dos recursos
}
});
}
Passo 8: Tornando sua PWA acessível
A acessibilidade é um aspecto crucial do desenvolvimento web moderno. Vamos tornar nossa PWA acessível para todos os usuários:
<!-- No arquivo index.html, modifique a estrutura: -->
<header>
<h1>Minha Primeira PWA</h1>
</header>
<main>
<p>Bem-vindo à minha primeira Progressive Web App!</p>
<div aria-live="polite" id="status"></div>
<button id="instalar" aria-label="Instalar aplicativo">Instalar App</button>
</main>
E no arquivo app.js
:
// Função para atualizar o status de forma acessível
function atualizarStatus(mensagem) {
const statusElement = document.getElementById('status');
statusElement.textContent = mensagem;
}
// Use esta função para informar o usuário sobre mudanças importantes
// Exemplo:
if (navigator.onLine) {
atualizarStatus('Você está online');
} else {
atualizarStatus('Você está offline. O app continuará funcionando com recursos limitados.');
}
window.addEventListener('online', () => {
atualizarStatus('Conexão restabelecida');
});
window.addEventListener('offline', () => {
atualizarStatus('Conexão perdida. Usando modo offline');
});
Passo 9: Publicando sua PWA na web
Quando sua PWA estiver pronta, é hora de publicá-la na web. Para isso, você precisará:
- Obter um domínio: Registre um domínio em serviços como Registro.br ou GoDaddy
- Contratar um serviço de hospedagem: Use serviços como Netlify, Vercel ou GitHub Pages
- Configurar HTTPS: O HTTPS é obrigatório para PWAs. Felizmente, serviços como Netlify e Vercel já oferecem HTTPS por padrão
- Fazer o upload dos arquivos: Envie todos os arquivos do seu projeto para o servidor
Exemplo de publicação no Netlify
O Netlify é uma opção gratuita e fácil para publicar sua PWA:
- Crie uma conta no Netlify
- Clique em “New site from Git”
- Conecte sua conta do GitHub, GitLab ou Bitbucket
- Selecione o repositório do seu projeto
- Configure as opções de build (não necessárias para projetos simples)
- Clique em “Deploy site”
Em poucos minutos, sua PWA estará online com HTTPS configurado automaticamente!
Passo 10: Monitorando e melhorando sua PWA
Depois de publicar sua PWA, é importante monitorar seu desempenho e fazer melhorias contínuas:
Ferramentas de análise e monitoramento
- Lighthouse: Ferramenta do Google para avaliar PWAs (integrada ao Chrome DevTools)
- Google Analytics: Para acompanhar o uso do seu app
- WebPageTest: Para analisar o desempenho em diferentes dispositivos e conexões
Checklist final de qualidade
Use esta checklist para verificar se sua PWA atende aos padrões de qualidade:
- [ ] Funciona offline
- [ ] É responsiva (adapta-se a qualquer tamanho de tela)
- [ ] Carrega rapidamente (menos de 3 segundos)
- [ ] Usa HTTPS
- [ ] É acessível
- [ ] Funciona em diferentes navegadores
- [ ] Pode ser instalada no dispositivo
- [ ] Envia notificações (se aplicável)
- [ ] Tem um bom desempenho mesmo em dispositivos de baixo custo
Conclusão
Parabéns! Você aprendeu a criar uma Progressive Web App do zero. Agora você tem o conhecimento necessário para desenvolver aplicativos web modernos, rápidos e confiáveis.
As PWAs representam o futuro do desenvolvimento web, combinando o melhor dos sites e dos aplicativos nativos. Com as técnicas que você aprendeu neste guia, pode criar experiências digitais que seus usuários vão adorar usar, independentemente do dispositivo ou da qualidade da conexão.
Lembre-se de que o desenvolvimento de PWAs é uma área em constante evolução. Continue aprendendo e experimentando novas técnicas para manter suas habilidades atualizadas.
Recursos adicionais
Para aprofundar seus conhecimentos sobre PWAs, confira estes recursos:
- Web.dev – Learn PWA – Guia oficial do Google sobre PWAs
- MDN Web Docs – Progressive Web Apps – Documentação detalhada da Mozilla
- PWA Builder – Ferramenta para criar PWAs rapidamente
- Workbox – Biblioteca do Google para facilitar o desenvolvimento de PWAs
- Can I Use – Verifique o suporte dos navegadores para recursos de PWA
Bom desenvolvimento!