---
sidebar_position: 12
title: "Build Offline (PWA)"
---

A plataforma suporta um modo de build offline que gera uma versão totalmente funcional sem acesso à internet, baseada em PWA com Workbox.

## Como funciona

```mermaid
graph TD
    CMD[pnpm build:offline] --> PRE1[build:letramento-assets\ncopia lucide.js]
    CMD --> PRE2[build:letramento-css\ngera letramento.css]
    PRE1 --> VITE[vite build --mode offline]
    PRE2 --> VITE
    VITE --> ENV[carrega .env.offline\nVITE_IS_OFFLINE=true]
    VITE --> BUNDLE[gera bundle em dist/]
    BUNDLE --> SW[gera dist/sw.js\nWorkbox precache]
    SW --> VAL[pnpm test:cache\nvalida precache]
```

O `--mode offline` faz o Vite carregar o arquivo `.env.offline`, que define `VITE_IS_OFFLINE=true`. O código pode ler essa variável via `import.meta.env.VITE_IS_OFFLINE` para ajustar comportamento em runtime.

O Service Worker é gerado automaticamente pelo plugin `vite-plugin-pwa` com Workbox e faz o precache de todos os assets do build.

## Diferença entre build normal e build offline

| Aspecto | `pnpm build` | `pnpm build:offline` |
|---|---|---|
| Vite mode | `production` | `offline` |
| `.env` carregado | `.env.production` | `.env.offline` |
| `VITE_IS_OFFLINE` | não definida | `true` |
| Service Worker | gerado | gerado (idêntico) |
| Precache | idêntico | idêntico |

A diferença prática está nas variáveis de ambiente — o bundle em si é o mesmo. O `build:offline` é usado para distribuição sem servidor (ex.: Electron ou cópia local em escola sem internet).

## O que é incluído no precache

O Workbox precacha automaticamente todos os arquivos do padrão:

```
**/*.{js,css,html,svg,png,json,ico,webp}
```

Os itens validados explicitamente pelo script `pnpm test:cache` são:

- `offline.html` — página de fallback quando sem conexão
- `atividades/letramento/**` — todas as atividades de letramento
- `letramento.css` — estilos das atividades de letramento
- `lucide.js` — biblioteca de ícones usada no letramento

A rota `/atividades/letramento/` está na deny list do `navigateFallback`, ou seja, nunca é substituída por `offline.html` mesmo sem conexão.

## Arquivos de referência

- `app/.env.offline` — define `VITE_IS_OFFLINE=true`
- `app/vite.config.js` — configuração do `VitePWA` e Workbox
- `app/public/offline.html` — página exibida ao usuário sem conexão
- `app/scripts/test-cache.mjs` — valida o precache do SW após o build

---

## Executando o build offline

### Pré-requisitos

- Node.js 20+
- pnpm instalado globalmente

### Linux (Debian e derivadas)

Clone o repositório e instale as dependências:

```bash
cd app
pnpm install
```

Execute o build offline:

```bash
pnpm build:offline
```

Valide o Service Worker gerado:

```bash
pnpm test:cache
```

O resultado estará em `app/dist/`.

Para servir localmente e testar o comportamento offline:

```bash
# instale um servidor estático se necessário
pnpm dlx serve dist
```

Abra o navegador em `http://localhost:3000`, vá em **DevTools → Application → Service Workers** e marque **Offline** para simular ausência de conexão.

### Windows

No Windows, o build roda dentro do WSL2 (recomendado) ou diretamente no PowerShell/CMD.

#### Opção 1 — WSL2 (recomendado)

Abra o terminal do WSL2 e siga os mesmos passos da seção Linux acima.

#### Opção 2 — PowerShell / CMD

Certifique-se de ter Node.js e pnpm instalados no Windows (veja [Pré-requisitos](../pre-requisitos.md)).

No PowerShell, dentro da pasta `app/`:

```powershell
pnpm install
pnpm build:offline
pnpm test:cache
```

> **Atenção:** O script `build:letramento-assets` usa `rm -f` (comando Unix). No PowerShell isso pode falhar. Use o WSL2 para evitar problemas com comandos de shell Unix embutidos nos scripts do `package.json`.

---

## Build para Electron

O script `electron:build` já usa `build:offline` internamente:

```bash
pnpm electron:build
```

Esse comando executa `pnpm build:offline` e em seguida empacota com `electron-builder`, gerando um instalador desktop com todos os assets offline incluídos.

---

## O que é o Electron e por que o usamos

Electron é um framework que empacota aplicações web (HTML/CSS/JS — neste caso, a aplicação em React) dentro de um runtime desktop (Chromium + Node.js), permitindo distribuir a mesma aplicação como um programa nativo para Windows, macOS e Linux.

- **Porque a aplicação é React**: a interface da plataforma é escrita em React; o Electron executa essa interface num navegador embutido, o que permite reaproveitar todo o código web sem reescrever a UI para cada sistema operacional.
- **Não é necessário Node.js na máquina do usuário**: o pacote gerado pelo `electron-builder` inclui o runtime necessário, portanto a máquina final NÃO precisa ter o Node.js ou dependências de desenvolvimento instaladas — o executável já contém tudo que é preciso para rodar offline.
- **Evita permissões administrativas na máquina final**: ao escolher alvos como `portable` no Windows ou empacotamentos que não exigem instalação com privilégios elevados, reduzimos a necessidade de permissões administrativas em ambientes escolares onde o educador pode não ter direitos de administrador.

> Observação: a fase de *build* e empacotamento pode exigir ferramentas nativas no ambiente de desenvolvimento (por exemplo, o empacotamento para Windows pode requerer dependências específicas). Porém, para execução offline nas máquinas finais, normalmente basta distribuir o executável gerado.

---

## Práticas recomendadas

1. Sempre rode `pnpm test:cache` após o build para garantir que o precache está completo.
2. Não distribua o build offline sem validar que `offline.html`, `letramento.css` e `lucide.js` estão no precache.
3. Ao adicionar novas atividades de letramento, verifique se os novos arquivos seguem o padrão de glob coberto pelo Workbox.
4. O Service Worker usa `autoUpdate` — ao servir uma versão nova, o SW se atualiza automaticamente no próximo carregamento do cliente.

Referências externas:

- vite-plugin-pwa: https://vite-pwa-org.netlify.app/
- Workbox: https://developer.chrome.com/docs/workbox/
- PWA no Chrome DevTools: https://developer.chrome.com/docs/devtools/progressive-web-apps/
