---
# System prepended metadata

title: SPA e PWA — Single Page Application e Progressive Web App

---

# 📘 SPA e PWA — Single Page Application e Progressive Web App
## Material Completo para Concursos — Estilo IDECAN

> **Banca:** IDECAN | **Área:** Tecnologia da Informação | **Nível:** Analista
>
> ⚡ **Perfil da Banca:** Citado literalmente no edital UNILAB 2026. Prioridade **média** no Bloco 1 (Dev Core). A IDECAN cobra diferenças conceituais SPA×MPA×PWA, os 3 componentes obrigatórios do PWA, ciclo de vida do Service Worker e estratégias de cache por cenário.

---

## 📋 Índice

1. [MPA — Multi-Page Application](#1-mpa--multi-page-application-modelo-tradicional)
2. [SPA — Single Page Application](#2-spa--single-page-application)
3. [MPA vs SPA — Comparativo](#3-mpa-vs-spa--comparativo)
4. [SSR, SSG e Hydration](#4-ssr-ssg-e-hydration)
5. [Client-Side Routing e Code Splitting](#5-client-side-routing-e-code-splitting)
6. [PWA — Progressive Web App](#6-pwa--progressive-web-app)
7. [Service Worker — Ciclo de Vida](#7-service-worker--ciclo-de-vida)
8. [Web App Manifest](#8-web-app-manifest)
9. [Estratégias de Cache](#9-estratégias-de-cache)
10. [Pegadinhas e Pontos-Chave da IDECAN](#10-pegadinhas-e-pontos-chave-da-idecan)
11. [Questões Comentadas no Estilo IDECAN](#11-questões-comentadas-no-estilo-idecan)

---

## 1. MPA — Multi-Page Application (modelo tradicional)

### Como funciona

No modelo **MPA**, cada navegação gera uma requisição HTTP ao servidor, que responde com uma página HTML **completa**. O navegador descarrega a página atual e carrega a nova inteiramente.

```
Usuário clica em link
    → Requisição HTTP ao servidor
    → Servidor gera e retorna HTML completo
    → Navegador recarrega a página inteira (flash branco)
    → Nova página é exibida
```

### Características

- Cada URL corresponde a um arquivo/rota no servidor que retorna HTML completo
- Recarregamento total a cada navegação
- SEO **nativo** — o servidor entrega HTML pronto para os crawlers
- Mais simples de desenvolver para casos básicos
- **Exemplos:** sistemas em PHP + Blade, JSP, Django templates, Ruby on Rails

---

## 2. SPA — Single Page Application

### Como funciona

No modelo **SPA**, uma única página HTML é carregada na primeira visita com todo o JavaScript da aplicação. Navegações subsequentes são feitas via **JavaScript** (AJAX/Fetch) — só os dados mudam, a página **não é recarregada**.

```
Primeira visita:
    → Baixa app completa (HTML + JS bundle + CSS)
    → Renderiza UI inicial

Navegações seguintes:
    → JS intercepta o clique no link
    → Busca apenas os dados necessários (JSON via API)
    → Atualiza apenas as partes do DOM que mudaram
    → URL muda via History API (sem req. ao servidor)
```

### Frameworks SPA Populares

- **React** (Meta/Facebook) — biblioteca de UI, Virtual DOM
- **Angular** (Google) — framework completo, TypeScript
- **Vue.js** — framework progressivo, MVVM
- **Svelte** — compila para JS puro (sem Virtual DOM em runtime)

### SPA e Back-end — Separação de Responsabilidades

```
┌─────────────────────────────┐    API REST/GraphQL    ┌──────────────────────────┐
│       Front-end SPA          │ ←────────────────────→ │      Back-end (API)       │
│  React / Vue / Angular       │      JSON via Fetch    │  Spring Boot / Laravel    │
│  - Renderiza UI              │                        │  - Retorna JSON           │
│  - Gerencia estado           │                        │  - NÃO gera HTML          │
│  - Roteamento no cliente     │                        │  - Reutilizável           │
└─────────────────────────────┘                        └──────────────────────────┘
```

O back-end torna-se uma **API pura** — o mesmo back-end pode servir a SPA, apps mobile e terceiros.

---

## 3. MPA vs SPA — Comparativo

| Característica | MPA | SPA |
|---|---|---|
| **Carregamento inicial** | Rápido (só a página atual) | Lento (baixa app inteira) |
| **Navegação posterior** | Lenta (recarrega tudo) | Rápida (só dados JSON) |
| **SEO** | Nativo (HTML pronto no servidor) | Desafiador (HTML gerado no cliente) |
| **Experiência do usuário** | Flash a cada navegação | Fluida, sem recarregamento |
| **Complexidade back-end** | Alta (gera HTML completo) | Baixa (só retorna JSON) |
| **Complexidade front-end** | Baixa | Alta (framework JS obrigatório) |
| **Roteamento** | Servidor | Cliente (History API) |
| **Estado da aplicação** | No servidor (sessão) | No cliente (Redux, Zustand) |
| **Exemplos** | PHP + Blade, JSP, Django | React, Angular, Vue |

> ⚠️ **IDECAN cobra:** No SPA, o carregamento **inicial** é mais **lento** (baixa toda a aplicação JS). As navegações **subsequentes** são mais rápidas. O SEO é o principal **desafio** das SPAs — o HTML inicial está quase vazio, dificultando indexação por buscadores.

---

## 4. SSR, SSG e Hydration

### Por que existem — O problema de SEO do SPA

O HTML inicial de uma SPA é quase vazio:

```html
<!-- HTML inicial de uma SPA típica -->
<html>
  <body>
    <div id="root"></div>          <!-- vazio! -->
    <script src="/bundle.js"></script>  <!-- conteúdo gerado pelo JS -->
  </body>
</html>
```

Os crawlers de busca (Google, Bing) têm dificuldade para indexar conteúdo gerado por JavaScript.

### SSR — Server-Side Rendering

O servidor **pré-renderiza** o HTML da SPA antes de enviar ao cliente. O usuário vê o conteúdo imediatamente e o JS assume o controle depois (hydration).

```
Cliente solicita /produto/123
    → Servidor executa React/Vue no servidor
    → Gera HTML completo com os dados do produto
    → Envia HTML pronto ao cliente (SEO + velocidade)
    → JS do cliente faz hydration (torna a página interativa)
```

**Frameworks SSR:** Next.js (React), Nuxt.js (Vue), Angular Universal, SvelteKit

### SSG — Static Site Generation

O HTML é gerado em **build-time** (não a cada requisição). Arquivos estáticos servidos por CDN — muito rápido.

```
Build:     npm run build → gera /produto/1.html, /produto/2.html...
Deploy:    arquivos estáticos no CDN
Requisição: CDN retorna HTML pré-gerado instantaneamente
```

**Ideal para:** blogs, documentação, landing pages (conteúdo que muda raramente).

### Hydration

Processo onde o JavaScript do framework "ativa" o HTML estático pré-renderizado pelo servidor, tornando-o **interativo**.

```
1. Servidor envia HTML pré-renderizado (página visível imediatamente)
2. Navegador recebe e exibe o HTML
3. JS da aplicação é baixado e executado
4. Framework "hidrata" — vincula eventos ao HTML existente
5. Página torna-se interativa (cliques, formulários funcionam)
```

> ⚠️ **IDECAN cobra:** SSR resolve o problema de SEO das SPAs gerando HTML no servidor. Next.js é o framework SSR mais cobrado no contexto de React.

---

## 5. Client-Side Routing e Code Splitting

### History API — Roteamento no Cliente

```javascript
// O SPA usa a History API do navegador para mudar URLs sem recarregar

// Adiciona uma entrada no histórico de navegação
history.pushState({ pagina: 'produtos' }, '', '/produtos');

// Substitui a entrada atual (sem criar nova entrada no histórico)
history.replaceState({ pagina: 'home' }, '', '/');

// Evento disparado ao clicar "Voltar"/"Avançar" no navegador
window.addEventListener('popstate', (event) => {
  console.log('Navegou para:', event.state);
});
```

### React Router — Roteamento em React

```jsx
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      {/* Link não recarrega a página — usa pushState internamente */}
      <Link to="/produtos">Produtos</Link>
      <Link to="/sobre">Sobre</Link>

      <Routes>
        <Route path="/"            element={<Home />} />
        <Route path="/produtos"    element={<ListaProdutos />} />
        <Route path="/produto/:id" element={<DetalheProduto />} />
        <Route path="*"            element={<PaginaNaoEncontrada />} />
      </Routes>
    </BrowserRouter>
  );
}
// Ao clicar no Link, a URL muda mas a página NÃO é recarregada
```

### Code Splitting — Dividindo o Bundle

**Problema:** SPAs podem ter bundles JS enormes (MBs), tornando o carregamento inicial muito lento.

**Solução:** dividir o código em partes (chunks) que são baixadas **sob demanda**.

```jsx
import React, { lazy, Suspense } from 'react';

// Carregamento lazy — o módulo só é baixado quando a rota é acessada
const DetalheProduto = lazy(() => import('./pages/DetalheProduto'));
const Relatorios = lazy(() => import('./pages/Relatorios'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Carregando...</div>}>
        <Routes>
          <Route path="/produto/:id" element={<DetalheProduto />} />
          <Route path="/relatorios"  element={<Relatorios />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}
// DetalheProduto.js só é baixado quando o usuário navega para /produto/...
```

---

## 6. PWA — Progressive Web App

### O que é PWA

**PWA (Progressive Web App)** é um conjunto de **tecnologias e padrões** que permitem que uma aplicação web ofereça experiência similar a um app nativo: funciona offline, pode ser instalada na tela inicial e recebe notificações push. Termo cunhado por Alex Russell (Google) em 2015.

### Os 4 Pilares do PWA

| Pilar | Descrição |
|---|---|
| **Confiável** | Funciona offline ou com rede instável. Service Worker cacheia recursos essenciais. |
| **Rápido** | Responde imediatamente às interações. Assets cacheados localmente. |
| **Envolvente (Engaging)** | Instalável na tela inicial. Push Notifications. Fullscreen. Experiência app-like. |
| **Segura** | HTTPS obrigatório. Service Worker só funciona em origens seguras. |

### Os 3 Componentes Obrigatórios do PWA ⭐

```
PWA = HTTPS + Service Worker + Web App Manifest
```

1. **HTTPS** — obrigatório para segurança; pré-requisito para o Service Worker funcionar
2. **Service Worker** — script em background que habilita offline e cache
3. **Web App Manifest** — arquivo JSON que permite instalação e define aparência

> ⚠️ **IDECAN cobra:** Os 3 componentes são **HTTPS + Service Worker + Web App Manifest**. A ausência de qualquer um impede que a aplicação seja classificada como PWA completo. HTTPS é pré-requisito para o Service Worker funcionar.

### PWA vs App Web vs App Nativo

| Característica | App Web | PWA | App Nativo |
|---|---|---|---|
| **Funciona offline** | Não | Sim | Sim |
| **Instalável** | Não | Sim (tela inicial) | Sim (App Store) |
| **Push Notifications** | Não | Sim | Sim |
| **Distribuição** | URL | URL (sem App Store) | App Store / Play Store |
| **Atualização** | Automática | Automática | Manual (aprovação) |
| **Acesso a hardware** | Limitado | Parcial (câmera, GPS) | Completo |
| **Performance** | Menor | Boa | Máxima |

> ⚠️ **IDECAN cobra:** PWA **não precisa** de App Store/Play Store para ser instalado — é instalado diretamente pelo navegador a partir da URL. Esta é uma das principais vantagens sobre apps nativos.

---

## 7. Service Worker — Ciclo de Vida

### O que é Service Worker

Script JavaScript que roda em uma **thread separada** da página (background), **sem acesso ao DOM**. Atua como um **proxy de rede** — intercepta todas as requisições feitas pela aplicação e decide o que fazer: buscar da rede, retornar do cache, ou combinar ambos.

### Características Importantes

- Roda em **background**, mesmo com a página fechada
- **Não tem acesso ao DOM** — usa `postMessage` para comunicar com a página
- Só funciona em **HTTPS** (exceto localhost para desenvolvimento)
- É um Worker baseado em **eventos** (event-driven)
- Tem acesso à **Cache API** para armazenar requisições/respostas

### Ciclo de Vida Completo ⭐

#### Fase 1 — Registration (Registro)

```javascript
// Na página principal (index.html ou App.js)
if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw.js')              // caminho para o arquivo do SW
    .then(reg => console.log('SW registrado, escopo:', reg.scope))
    .catch(err => console.error('Falha no registro:', err));
}
```

#### Fase 2 — Install (Instalação) — momento do pre-caching

```javascript
// Dentro do arquivo sw.js
const CACHE_NAME = 'meu-app-v1';
const ARQUIVOS_PARA_CACHE = [
  '/',
  '/index.html',
  '/app.js',
  '/styles.css',
  '/icons/logo.png'
];

self.addEventListener('install', event => {
  console.log('SW: instalando...');
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('SW: realizando pre-caching dos arquivos essenciais');
        return cache.addAll(ARQUIVOS_PARA_CACHE);
      })
  );
  // self.skipWaiting() força ativação imediata (pula a espera)
});
```

#### Fase 3 — Activate (Ativação) — momento da limpeza

```javascript
self.addEventListener('activate', event => {
  console.log('SW: ativando...');
  event.waitUntil(
    caches.keys().then(nomesDeCache =>
      Promise.all(
        nomesDeCache
          .filter(nome => nome !== CACHE_NAME)  // caches de versões antigas
          .map(nome => {
            console.log('SW: removendo cache antigo:', nome);
            return caches.delete(nome);
          })
      )
    )
  );
  // self.clients.claim() faz o SW assumir controle imediatamente
});
```

#### Fase 4 — Fetch (Operação Normal) — interceptação de requisições

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(respostaDoCche => {
        if (respostaDoCche) {
          return respostaDoCche;  // retorna do cache
        }
        return fetch(event.request);  // busca na rede
      })
  );
});
```

### Outros Eventos do Service Worker

| Evento | Quando dispara | Uso |
|---|---|---|
| `push` | Mensagem push recebida do servidor | Exibir notificação push |
| `notificationclick` | Usuário clica na notificação | Abrir URL específica |
| `sync` | Conexão restabelecida | Background Sync — enviar dados enfileirados offline |
| `message` | Página envia postMessage | Comunicação bidirecional com a página |

### Resumo do Ciclo de Vida

```
Register → Install (pre-caching) → Activate (limpar caches antigos)
                                          ↓
                               Fetch (interceptar requisições)
                               Push (notificações)
                               Sync (background sync)
```

> ⚠️ **IDECAN cobra:** A ordem é **Register → Install → Activate → Fetch**. O evento **install** é para **pre-caching**. O evento **activate** é para **limpeza de caches antigos**. O evento **fetch** intercepta requisições em operação normal.

---

## 8. Web App Manifest

### O que é

Arquivo **JSON** (`manifest.json`) que fornece informações sobre o PWA ao navegador e ao SO: nome, ícones, cores, modo de exibição. Permite que o usuário **instale o app** na tela inicial com aparência nativa.

### Exemplo Completo

```json
{
  "name": "Meu App Completo",
  "short_name": "MeuApp",
  "description": "Aplicação PWA de exemplo para concurso",
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "orientation": "portrait",
  "background_color": "#ffffff",
  "theme_color": "#1D9E75",
  "lang": "pt-BR",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "shortcuts": [
    {
      "name": "Novo Pedido",
      "url": "/pedidos/novo",
      "icons": [{ "src": "/icons/new.png", "sizes": "96x96" }]
    }
  ]
}
```

### Propriedade `display` — Modos de Exibição ⭐

| Valor | Descrição | Uso |
|---|---|---|
| **`standalone`** | Remove barra de endereço. Mantém barra de status do SO. Parece app nativo. | **Mais comum em PWAs** |
| `fullscreen` | Remove toda a UI do navegador e do SO. Tela inteira. | Jogos |
| `minimal-ui` | Controles mínimos de navegação (voltar, recarregar). Sem barra de endereço. | Intermediário |
| `browser` | Abre no navegador normalmente, com interface completa. | Padrão — sem experiência app-like |

> ⚠️ **IDECAN cobra:** O modo **`standalone`** é o que dá a experiência "app-like" ao PWA — remove a barra de endereço do navegador. É o valor mais cobrado. `fullscreen` é para jogos e remove absolutamente tudo.

### Como Referenciar no HTML

```html
<!-- No <head> do index.html -->
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#1D9E75">

<!-- Meta tags para iOS (Safari tem suporte parcial ao manifest) -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="MeuApp">
<link rel="apple-touch-icon" href="/icons/icon-192.png">
```

---

## 9. Estratégias de Cache

### Cache API — Armazenamento de Requisições

```javascript
// Abrir/criar um cache pelo nome
const cache = await caches.open('meu-cache-v1');

// Armazenar uma resposta manualmente
await cache.put(request, response);

// Buscar e armazenar automaticamente
await cache.add('/pagina.html');
await cache.addAll(['/app.js', '/styles.css', '/logo.png']);

// Buscar no cache
const resposta = await cache.match(request);

// Remover um item
await cache.delete(request);

// Listar todos os caches existentes
const nomesDosCaches = await caches.keys();

// Deletar um cache inteiro
await caches.delete('meu-cache-v1');
```

### As 5 Estratégias de Cache ⭐

#### 1. Cache First (cache → rede)

Busca no cache primeiro. Se não encontrar, vai à rede. Ideal para assets **estáticos** que raramente mudam.

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      return cached || fetch(event.request).then(response => {
        // opcional: salvar no cache ao buscar da rede
        caches.open(CACHE_NAME).then(cache => cache.put(event.request, response.clone()));
        return response;
      });
    })
  );
});
```

**Quando usar:** imagens, fontes, CSS, JS da aplicação, ícones.

#### 2. Network First (rede → cache)

Tenta a rede primeiro. Se falhar (offline), usa o cache como fallback.

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
      .then(response => {
        // salva a resposta no cache para uso offline
        const responseClone = response.clone();
        caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseClone));
        return response;
      })
      .catch(() => caches.match(event.request)) // fallback offline
  );
});
```

**Quando usar:** feeds de notícias, dados de perfil, conteúdo dinâmico que precisa estar atualizado.

#### 3. Stale While Revalidate

Retorna do cache **imediatamente** (rápido) e, em paralelo, atualiza o cache com a versão mais recente da rede. Na próxima requisição, o conteúdo já estará atualizado.

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.open(CACHE_NAME).then(cache =>
      cache.match(event.request).then(cached => {
        // atualiza o cache em segundo plano
        const networkFetch = fetch(event.request).then(response => {
          cache.put(event.request, response.clone());
          return response;
        });
        // retorna o cache imediatamente (se existir) ou aguarda a rede
        return cached || networkFetch;
      })
    )
  );
});
```

**Quando usar:** avatares de usuário, páginas que mudam com frequência moderada, APIs que toleram dados ligeiramente desatualizados.

#### 4. Cache Only

Sempre usa o cache. Nunca vai à rede. Para recursos **pre-cacheados** no install que não mudam.

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(caches.match(event.request));
});
```

**Quando usar:** app shell (HTML/CSS/JS core), assets de versão fixada.

#### 5. Network Only

Sempre usa a rede. Nunca cacheia. Para requisições que **não devem** ser cacheadas.

```javascript
self.addEventListener('fetch', event => {
  event.respondWith(fetch(event.request));
});
```

**Quando usar:** analytics, pagamentos, dados em tempo real críticos, requisições POST de escrita.

### Tabela de Decisão — Qual Estratégia Usar?

| Cenário | Estratégia Recomendada |
|---|---|
| Imagens, fontes, CSS, JS | Cache First |
| Feed de notícias, dados dinâmicos | Network First |
| Perfil do usuário, thumbnails | Stale While Revalidate |
| HTML/CSS do app shell (core) | Cache Only |
| Pagamentos, analytics, POST | Network Only |
| Offline + dados mais recentes possíveis | Network First |
| Velocidade máxima + eventual atualização | Stale While Revalidate |

> ⚠️ **IDECAN cobra:** Questões apresentam cenários e pedem qual estratégia aplicar. "Usuário offline, precisa ver último conteúdo" → **Network First**. "Assets estáticos, raramente mudam" → **Cache First**. "Equilíbrio velocidade + atualização" → **Stale While Revalidate**.

### Workbox — Biblioteca do Google para Service Workers

```javascript
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';

// Imagens — Cache First com expiração de 30 dias
registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'imagens',
    plugins: [new ExpirationPlugin({ maxAgeSeconds: 30 * 24 * 60 * 60 })]
  })
);

// API REST — Network First
registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new NetworkFirst({ cacheName: 'api-cache' })
);

// CSS e JS — Stale While Revalidate
registerRoute(
  ({ request }) => request.destination === 'style' || request.destination === 'script',
  new StaleWhileRevalidate({ cacheName: 'assets' })
);
```

---

## 10. Pegadinhas e Pontos-Chave da IDECAN

### ❌ Afirmações FALSAS (distratores clássicos)

1. ~~"No SPA, o carregamento inicial é mais rápido que no MPA"~~ → **FALSO**. O carregamento **inicial** do SPA é mais **lento** (baixa toda a aplicação JS). As navegações **subsequentes** são mais rápidas.

2. ~~"Um PWA precisa ser publicado na App Store ou Google Play para ser instalado"~~ → **FALSO**. PWA é instalado **diretamente pelo navegador** a partir da URL, sem loja de apps.

3. ~~"O Service Worker tem acesso direto ao DOM para manipulá-lo"~~ → **FALSO**. Service Worker **não tem acesso ao DOM** — roda em thread separada. Para comunicar com a página usa **`postMessage`**.

4. ~~"Service Workers podem ser registrados em origens HTTP simples"~~ → **FALSO**. Service Workers **só funcionam em HTTPS** (exceto localhost para desenvolvimento).

5. ~~"O evento 'install' do SW é o momento para limpar caches antigos"~~ → **FALSO**. Limpeza de caches antigos deve ocorrer no **'activate'**. O **'install'** é para **pre-caching** dos arquivos essenciais.

6. ~~"O modo 'fullscreen' no manifest é o mais usado para dar experiência app-like"~~ → **FALSO**. O modo mais comum em PWAs é **'standalone'**. `fullscreen` é para jogos.

7. ~~"Cache First é ideal para APIs REST com dados dinâmicos"~~ → **FALSO**. Cache First é para **assets estáticos**. Para APIs dinâmicas usa-se **Network First** ou Stale While Revalidate.

8. ~~"SPA e PWA são a mesma coisa"~~ → **FALSO**. São conceitos **independentes e complementares**. SPA = arquitetura de navegação. PWA = conjunto de tecnologias para offline/app-like. Um SPA pode ou não ser um PWA.

9. ~~"O carregamento SSR é exclusivo de MPAs — SPAs não podem usar SSR"~~ → **FALSO**. **Next.js** e **Nuxt.js** fazem SSR de SPAs React e Vue, respectivamente, resolvendo o problema de SEO.

10. ~~"Service Worker é um componente opcional do PWA"~~ → **FALSO**. Service Worker é um dos **3 componentes obrigatórios** — sem ele não há offline e a aplicação não é um PWA completo.

### ✅ Afirmações VERDADEIRAS (fixe!)

1. Os 3 componentes obrigatórios do PWA são **HTTPS + Service Worker + Web App Manifest**.
2. O ciclo de vida do Service Worker é **Register → Install → Activate → Fetch**.
3. O evento **`install`** é o momento do **pre-caching** (cachear assets essenciais).
4. O evento **`activate`** é o momento de **limpar caches antigos**.
5. O modo **`standalone`** no manifest remove a barra de endereço e dá experiência app-like.
6. SPA tem SEO desafiador porque o HTML inicial está quase vazio — conteúdo é gerado por JS no cliente.
7. **Next.js** resolve o SEO das SPAs React usando SSR (Server-Side Rendering).
8. **Stale While Revalidate**: retorna do cache imediatamente E atualiza o cache em segundo plano.
9. PWA não requer App Store — é instalado pelo navegador diretamente a partir da URL.
10. Service Worker só funciona em **HTTPS** (ou localhost para desenvolvimento).
11. **Code splitting** divide o bundle JS em chunks carregados sob demanda — reduz tempo de carregamento inicial do SPA.
12. No Web App Manifest, o campo **`start_url`** define qual URL abre quando o usuário lança o app instalado.

---

## 11. Questões Comentadas no Estilo IDECAN

---

### Questão 1

**Qual é a principal diferença entre SPA e MPA no carregamento de páginas?**

- A) No SPA, cada navegação gera uma requisição HTTP que retorna HTML completo do servidor.
- B) No SPA, uma única página HTML é carregada inicialmente e o JS atualiza o DOM com dados via AJAX; no MPA, cada navegação recarrega a página completa do servidor.
- C) SPA e MPA são equivalentes — a diferença é apenas o framework utilizado.
- D) No SPA, o SEO é mais eficiente que no MPA porque o conteúdo é gerado no cliente.
- E) No MPA, o JavaScript controla toda a navegação sem recarregar páginas.

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: B**

**Comentário:** No SPA, uma única página HTML é carregada com todo o JavaScript. Navegações subsequentes atualizam apenas partes do DOM via AJAX/Fetch, sem recarregar a página. No MPA, cada clique gera uma requisição HTTP ao servidor que retorna HTML completo — a página recarrega inteiramente. O SEO é o principal **desafio** (não vantagem) do SPA, pois o HTML inicial está quase vazio.

</details>

---

### Questão 2

**Quais são os 3 componentes obrigatórios para que uma aplicação seja classificada como PWA completa?**

- A) React.js, Service Worker e localStorage
- B) HTTPS, Service Worker e Web App Manifest
- C) Service Worker, WebSocket e IndexedDB
- D) Web App Manifest, Push Notifications e HTTPS
- E) Angular, Service Worker e Cache API

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: B**

**Comentário:** Os 3 componentes obrigatórios são: (1) **HTTPS** — obrigatório para segurança e pré-requisito do Service Worker; (2) **Service Worker** — proxy de rede que habilita offline e cache; (3) **Web App Manifest** — arquivo JSON que permite instalação e define aparência app-like. React, WebSocket, Push Notifications e IndexedDB são opcionais. A alternativa D troca Service Worker por Push Notifications, que é apenas uma funcionalidade do SW.

</details>

---

### Questão 3

**Sobre o Service Worker, assinale a alternativa CORRETA:**

- A) O Service Worker tem acesso direto ao DOM para atualizar elementos da página.
- B) O Service Worker pode ser registrado em origens HTTP simples para facilitar o desenvolvimento.
- C) O Service Worker roda em thread separada, sem acesso ao DOM, e intercepta requisições de rede.
- D) O Service Worker substitui o localStorage para armazenamento persistente offline.
- E) O Service Worker é executado na mesma thread da página, compartilhando o contexto JavaScript.

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: C**

**Comentário:** O Service Worker roda em uma thread separada (background), completamente independente da página. **Não tem acesso ao DOM** — usa `postMessage` para comunicar com a página. Intercepta requisições de rede (evento `fetch`) e decide o que retornar (cache ou rede). Só funciona em **HTTPS** (exceto localhost). Não é substituto do localStorage — é um proxy de rede com Cache API.

</details>

---

### Questão 4

**No ciclo de vida do Service Worker, em qual evento deve ser realizado o pre-caching dos arquivos essenciais da aplicação?**

- A) No evento `register` — antes de instalar o SW
- B) No evento `install` — quando o SW é instalado pela primeira vez
- C) No evento `activate` — quando o SW assume o controle das páginas
- D) No evento `fetch` — quando a primeira requisição é interceptada
- E) No evento `push` — quando uma notificação push é recebida

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: B**

**Comentário:** O evento **`install`** é disparado quando o Service Worker é instalado pela primeira vez — é o momento ideal para o **pre-caching** dos arquivos essenciais (HTML, CSS, JS, ícones) usando `event.waitUntil()` com `caches.addAll()`. O evento **`activate`** é para limpar caches de versões anteriores. O evento **`fetch`** é para interceptar requisições durante o uso normal.

</details>

---

### Questão 5

**Uma aplicação de notícias deve exibir conteúdo atualizado sempre que online, mas também mostrar as últimas notícias quando offline. Qual estratégia de cache é mais adequada?**

- A) Cache First — retorna do cache, nunca vai à rede
- B) Cache Only — usa apenas o cache pré-definido
- C) Network First — tenta a rede primeiro, usa o cache como fallback quando offline
- D) Stale While Revalidate — retorna do cache e atualiza em segundo plano
- E) Network Only — sempre usa a rede, sem fallback

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: C**

**Comentário:** **Network First** é a estratégia correta para conteúdo dinâmico (notícias) que precisa estar atualizado quando online, mas disponível offline. O SW tenta a rede primeiro — com conexão, retorna dados frescos e atualiza o cache. Sem conexão, usa o cache como fallback. Cache First priorizaria dados antigos mesmo com internet. Stale While Revalidate retornaria o cache imediatamente (possivelmente desatualizado) mesmo estando online.

</details>

---

### Questão 6

**Sobre o campo `display` no Web App Manifest, qual valor remove a barra de endereço do navegador e dá ao PWA aparência de aplicativo nativo?**

- A) `fullscreen` — remove toda a UI do navegador e do sistema operacional
- B) `browser` — abre no navegador com interface completa
- C) `standalone` — remove a barra de endereço mas mantém barra de status do SO
- D) `minimal-ui` — exibe apenas controles básicos de navegação
- E) `native` — emula completamente a experiência de app nativo

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: C**

**Comentário:** **`standalone`** é o modo mais usado em PWAs — remove a barra de endereço do navegador, dando experiência app-like, mas mantém a barra de status do SO (horário, bateria). `fullscreen` remove **toda** a UI (inclusive SO) e é usado em jogos. `browser` é o padrão sem experiência app-like. `minimal-ui` mantém controles básicos de navegação. `native` não é um valor válido do manifest.

</details>

---

### Questão 7 (Certo/Errado — estilo IDECAN)

*"SPA e PWA são conceitos equivalentes — uma SPA é necessariamente uma PWA, pois ambas dispensam o recarregamento de página e oferecem experiência similar a aplicativos nativos."*

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: ERRADO**

**Comentário:** SPA e PWA são conceitos **independentes e complementares**, não equivalentes. **SPA** é uma arquitetura de navegação — uma página HTML com roteamento no cliente via JavaScript. **PWA** é um conjunto de tecnologias (HTTPS + Service Worker + Manifest) que adiciona capacidades offline, instalação e notificações push. Uma SPA pode ser um PWA (Twitter Lite, por exemplo), mas não necessariamente. Uma MPA tradicional também pode ser um PWA se adicionar Service Worker e Manifest. São dimensões diferentes: SPA descreve *como a navegação funciona*; PWA descreve *quais capacidades a aplicação possui*.

</details>

---

### Questão 8 (Certo/Errado)

*"O evento `activate` do Service Worker é o momento recomendado para limpar caches de versões anteriores, pois nesta fase o SW já assumiu o controle das páginas e é seguro remover recursos que não serão mais usados."*

<details>
<summary>🔎 Ver resposta e comentário</summary>

**✅ Resposta: CERTO**

**Comentário:** Afirmação correta. O evento `activate` é disparado após o SW ser instalado e estar pronto para assumir o controle. É o momento ideal para remover caches de versões anteriores (ex: `meu-app-v1` quando a versão atual é `meu-app-v2`), garantindo que o espaço de armazenamento não seja desperdiçado com recursos obsoletos. O evento `install` (fase anterior) é para criar o novo cache com os arquivos da versão atual. Tentar deletar caches antigos no `install` pode causar problemas de concorrência com o SW anterior ainda em execução.

</details>

---

## 📌 Resumo Visual — Comparativo Final

```
                 SPA                          PWA
         ┌──────────────────┐        ┌──────────────────┐
         │ Uma página HTML  │        │ HTTPS obrigatório│
         │ Roteamento no JS │        │ Service Worker   │
         │ AJAX para dados  │        │ Web App Manifest │
         │ React/Vue/Angular│        │ Offline-first    │
         │ Desafio: SEO     │        │ Instalável       │
         └──────────────────┘        └──────────────────┘
                 ↑                           ↑
                 └──────────┬────────────────┘
                            │
                   Podem ser usados
                   juntos (SPA + PWA)
                   ou separadamente
```

---

## 📚 Tabela de Referência Rápida

| Conceito | Resumo |
|---|---|
| SPA | Uma página HTML + JS atualiza DOM via AJAX — sem recarregamento |
| MPA | Cada navegação = nova requisição HTTP + HTML completo do servidor |
| SEO no SPA | Desafiador (HTML inicial vazio) — solução: SSR com Next.js/Nuxt |
| SSR | Servidor pré-renderiza HTML da SPA — combina SEO + experiência SPA |
| Code Splitting | Divide bundle JS em chunks carregados sob demanda |
| PWA | HTTPS + Service Worker + Web App Manifest |
| Service Worker | Proxy de rede em thread separada, sem acesso ao DOM, só HTTPS |
| SW — install | Pre-caching dos arquivos essenciais |
| SW — activate | Limpeza de caches de versões antigas |
| SW — fetch | Interceptação de requisições em operação normal |
| Cache First | Cache → rede. Para assets estáticos. |
| Network First | Rede → cache (fallback offline). Para dados dinâmicos. |
| Stale While Revalidate | Cache imediato + atualiza em background. Para equilíbrio. |
| manifest display | `standalone` = app-like (sem barra de endereço) |
| PWA instalação | Via navegador, sem App Store / Play Store |
| Workbox | Biblioteca Google que abstrai Service Worker e estratégias de cache |

---

*Material elaborado com base no perfil de cobrança histórico da banca IDECAN (2006–2026).*
*Última atualização: 2026*
