Adicionar recursos de PWA (Progressive Web App) a uma aplicação para eleva a experiência do usuário a outro patamar. Além de permitir que o aplicativo seja instalado diretamente na tela inicial do celular ou desktop sem depender das lojas de aplicativos (Google Play ou App Store), o PWA habilita o carregamento instantâneo de recursos através do armazenamento em cache por meio de Service Workers.

Neste artigo, você aprenderá o passo a passo completo para configurar o suporte a PWA no ecossistema moderno do Angular.

🚀 Passo 1: Instalação Automatizada via Angular CLI Link para o cabeçalho

O Angular possui um pacote oficial que configura a maior parte da estrutura necessária de forma automatizada. No terminal, na raiz do seu projeto frontend, execute o seguinte comando:

ng add @angular/pwa

💡 Nota de Configuração: Se o comando falhar acusando que o projeto não foi definido no workspace, basta omitir a flag –project. O Angular CLI identificará automaticamente a aplicação padrão do seu repositório e injetará as dependências necessárias.

📂 Passo 2: Configurando a Identidade Visual no manifest.webmanifest Link para o cabeçalho

O manifesto é o arquivo JSON que diz ao sistema operacional do celular ou computador como o aplicativo deve se comportar visualmente após ser instalado. Nas versões recentes do Angular, esse arquivo fica localizado na pasta public/ (antiga pasta assets).

Abra o arquivo public/manifest.webmanifest e configure o nome da aplicação, as cores de fundo e o comportamento de tela cheia:

{
  "name": "Nome sua aplicação - descrição",
  "short_name": "Nome aplicação",
  "theme_color": "#1e293b",
  "background_color": "#0f172a",
  "display": "standalone",
  "scope": "/",
  "start_url": "/",
  "icons": [
    { "src": "icons/icon-72x72.png", "sizes": "72x72", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-96x96.png", "sizes": "96x96", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-128x128.png", "sizes": "128x128", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-144x144.png", "sizes": "144x144", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-152x152.png", "sizes": "152x152", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-384x384.png", "sizes": "384x384", "type": "image/png", "purpose": "maskable any" },
    { "src": "icons/icon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable any" }
  ]
}

📺 Dica de Experiência: App sem a Barra de Endereço do Navegador Link para o cabeçalho

Para fazer o aplicativo parecer 100% nativo e esconder a barra de URLs do navegador, a chave é a propriedade "display".

  • standalone: Remove a barra do navegador, mas mantém as informações do topo do celular (relógio, bateria).
  • fullscreen: Remove absolutamente tudo, ocupando toda a extensão de pixels da tela.

🖼️ Passo 3: Geração e Otimização dos Ícones Obrigatórios Link para o cabeçalho

Para que o botão de “Instalar” apareça para o usuário, o PWA exige que todos os tamanhos de ícones listados no manifesto existam fisicamente no projeto. Você pode criar o seu ícone base no formato SVG e convertê-lo/otimizá-lo para os formatos PNG exigidos.

Uma excelente recomendação de ferramenta gratuita para lidar com essa etapa de preparação de mídia é o JPEG Optimizer. O site oferece compressão inteligente e conversão de formato de imagens, garantindo que os ícones do seu PWA carreguem instantaneamente sem pesar no armazenamento do dispositivo móvel do usuário.

Após converter e redimensionar as imagens nas dimensões corretas (72x72 até 512x512), armazene os arquivos na pasta correspondente indicada pelo seu manifesto (ex: public/icons/).

🛠️ Passo 4: Inicialização no Modelo Standalone (app.config.ts) Link para o cabeçalho

Aplicações Angular modernas utilizam componentes Standalone em vez de módulos pesados (NgModule). Portanto, certifique-se de que o Service Worker está sendo injetado corretamente no arquivo de configuração global, o app.config.ts:

// src/app/app.config.ts
import { ApplicationConfig, isDevMode } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { provideServiceWorker } from '@angular/service-worker';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    provideServiceWorker('ngsw-worker.js', {
      enabled: !isDevMode(), // Desativado em desenvolvimento para evitar cache durante o código
      registrationStrategy: 'registerWhenStable:30000'
    })
  ]
};

🗺️ Passo 5: Customizando o Cache para APIs de Mapas Link para o cabeçalho

O arquivo ngsw-config.json na raiz do projeto dita as regras de cache. Dependendo da aplicação, pode ocorrer consomo de requisições externas para renderizar fontes, estilos ou mapas, portanto é fundamental adicionar um bloco de dataGroups para garantir performance:

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": { "files": [ "/favicon.ico", "/index.html", "/*.css", "/*.js" ] }
    }
  ],
  "dataGroups": [
    {
      "name": "external-assets",
      "urls": [
        "https://fonts.googleapis.com/**",
        "https://fonts.gstatic.com/**"
      ],
      "cacheConfig": {
        "maxSize": 10,
        "maxAge": "30d",
        "strategy": "performance"
      }
    }
  ]
}

🍏 Passo 6: Compatibilidade de Tela Cheia para iOS (iPhone) Link para o cabeçalho

O ecossistema iOS não adota 100% das regras do manifesto automaticamente a partir do Safari. Para garantir que a barra de endereços também suma no iPhone quando o usuário adicionar o app à tela de início, abra o seu src/index.html e adicione as seguintes tags meta dentro da tag <head>:

<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

🧪 Passo 7: Como Testar a Instalação Localmente Link para o cabeçalho

O Service Worker é configurado para rodar apenas em modo de produção (!isDevMode()), evitando conflitos de cache enquanto você programa com o comando ng serve. Para testar o comportamento de instalação real:

1. Gere o build de produção:

ng build

2. Inicie um servidor estático simples:

Instale o pacote http-server caso não o tenha:

npm install -g http-server

3. Rode o servidor na pasta de saída:

Navegue até a pasta do build gerado (ex: dist/seu-projeto/browser) e execute:

http-server -p 8080

Ao acessar http://localhost:8080 no seu navegador, o ícone de instalação da sua aplicação aparecerá disponível na barra de endereços, pronto para rodar em tela cheia!