AngularJS Frontend¶
Visão Geral¶
O frontend da aplicação UNICEF Portugal é uma Single Page Application (SPA) construída com AngularJS 1.x. Não é um processo separado -- é HTML e JavaScript estático servido a partir do mesmo Azure App Service que aloja o Umbraco.
Como é Carregado¶
O AngularJS não corre separadamente do Umbraco. É carregado através de um template Razor do Umbraco chamado StartView.cshtml (Web/Views/StartView.cshtml).
Este template:
- Herda de
UmbracoTemplatePage(é um template Umbraco normal) - Carrega o nó da homepage para obter o ID do Google Analytics
- Renderiza a página HTML completa com
<html ng-app="unicef"> - Inclui os ficheiros CSS e JS da aplicação Angular (versão minificada)
- Define a estrutura de layout: sidebar, header,
<main ui-view>, footer
Quando o Umbraco recebe um pedido para qualquer URL, serve este template. O AngularJS então "toma conta" da navegação no browser, fazendo chamadas à API para obter o conteúdo de cada página.
Umbraco (StartView.cshtml)
└── Serve HTML com ng-app="unicef"
└── AngularJS faz bootstrap
└── ui-router intercepta navegação
└── Chama /umbraco/Api/ContentApi/GetData/
└── Renderiza template de /Assets/ngviews/
Ficheiros Fonte¶
- Desenvolvimento:
Templates/app/index.html(versão não minificada, para referência) - Produção: O template Umbraco
StartView.cshtmlcarrega/Assets/js/main.min.jse/Assets/css/main.min.css - IIS Express (local): Porta SSL 44388 (
https://localhost:44388)
Routing¶
A aplicação utiliza angular-ui-router com HTML5 mode:
$locationProvider.html5Mode(true);
Existe um unico estado chamado "all" com uma rota catch-all:
URL: *myPath?q
Este estado intercepta toda a navegação do browser.
Fluxo de Carregamento¶
Ciclo de Vida de um Pedido¶
- O utilizador navega para um URL (ex:
/noticias/artigo-exemplo) - O
ui-routerintercepta via catch-all*myPath - No
resolvedo estado, é feita uma chamada à API:GET /umbraco/Api/ContentApi/GetData/?url=/noticias/artigo-exemplo - A API retorna JSON com dois blocos:
data: título, corpo, imagem, e outros campos do conteúdometa: caminho do template (ex:"/Assets/ngviews/newsDetail.html")- O controller processa a resposta: define crops de imagens, URL do template, links de partilha
- O template e carregado via
ng-include:<div ng-include="vm.pageData.templateUrl"></div>
Estrutura de Layout¶
Os componentes de layout são carregados via ng-include:
sidebar.html- Barra lateralheader.html- Cabeçalho- main (
ui-view) - Conteúdo dinâmico, muda com cada página footer.html- Rodapé
Templates¶
Os templates estão organizados em /Assets/ngviews/:
Assets/ngviews/
components/ -- Componentes reutilizáveis
layout/ -- Estrutura de layout (header, footer, sidebar)
*.html -- Templates de pagina (newsDetail, articleDetail, etc.)
Configuracao¶
No Web.config existe a seguinte definicao:
<add key="Template.Path" value="Assets/ngviews/" />
Esta configuração define o caminho base para os templates do frontend.
Versões: app vs dist¶
| Pasta | Uso | Descrição |
|---|---|---|
Templates/app/ |
Desenvolvimento | Código fonte original, não minificado |
Templates/dist/ |
Produção | Build de produção, ficheiros minificados e concatenados |
Impacto na Performance
Se o ContentApiController estiver lento (por exemplo, devido a bloat na base de dados com 1.6M de registos na tabela icUrlTracker), o spinner de carregamento fica visível indefinidamente. Isto acontece porque o AngularJS aguarda a resposta completa da API antes de renderizar qualquer conteúdo na página. Não existe timeout nem fallback -- a página simplesmente não carrega.