Frontend Web
Tecnologias Utilizadas
O frontend web tem como base os seguintes frameworks JavaScript:
-
React
, como alicerce da arquitetura -
Next.js
, para estrutura geral da aplicação SPA (Single Page Application) -
PrimeReact
, como suite de componentes de UI -
PrimeFlex
, para tema, layouts e estilos padronizados -
PrimeIcons
, complemento de ícones do PrimeReact -
FontAwesome free
, catálogo de ícones amplamente usado -
Normalize
, reset de CSS -
Cloudsupport for React
, que oferece componentes estruturais
Os apps de frontend web utilizam como dependência a biblioteca Node react-cloudsupport
,
que inclui módulos e componentes para aumentar produtividade dos desenvolvedores bem como auxiliar
o cumprimento dos padrões e convenções de código definidos ao longo deste manual. Dessa forma o
código-fonte dos projetos fica enxuto e o desenvolvedor poderá focar naquilo que lhe é
útil: construir as páginas.
Considere o exemplo cloudsupport-archetype-frontweb
como ponto de partida para novos
projetos bem como para acompanhar a leitura deste manual e melhor assimilar os conceitos.
Observação: O Cloudsupport
não é restrito ao Next.js e PrimeReact. Conforme a necessidade
do projeto, outros frameworks podem ser utilizados, como por exemplo a suite de componentes
de UI Mantine
ou PatternFly
. O Next.js e PrimeReact são indicados para aplicações de uso geral e serão
considerados nas seções seguintes.
Funcionalidades da Arquitetura
São funcionalidades oferecidas pela biblioteca Cloudsupport for React
:
-
Módulo que oferece uma solução de profile configurável em runtime, em que as propriedades por ambiente podem ser definidas após o build da aplicação, como, por exemplo, no momento da execução do container Docker.
-
Hook
useProfile
para acesso ao profile. -
Componente que exibe aviso de que a aplicação tem atualização pendente, quando há mudanças no profile.
-
Integração OIDC, com suporte a todos os tokens (JWT, Refresh Token, ID Token e User Info), através de extensões e pré-configuração do framework
React OIDC Context
. -
Componente
AuthRequired
para proteger páginas que requerem autenticação via SSO OIDC. -
Injeção automática do Access Token (JWT) nos requests webservice, o que permite autenticar de maneira transparente as requisições para o backend.
-
Injeção automática de parâmetro nas requisições webservice que permite ao backend identificar a origem das requisições (nome e versão da aplicação de frontend).
-
Rotina automática de refresh do Access Token (JWT), de forma a desonerar o desenvolvedor do esforço de manter a autenticação OIDC viva.
-
Fluxo de redirect de pós login, que faz retorno para a página onde o usuário estava antes da autenticação, preservando-se os parâmetros iniciais de URL.
-
Fluxo de redirect de pós logout, em que o OIDC redireciona o usuário para uma página de “sessão encerrada” da aplicação.
-
Módulo para propagação de logout para todas as abas do browser.
-
Componente React integrado ao OIDC que exibe aviso de sessão expirada.
-
Hook
useAuth
para simplificar o acesso aos dados do usuário autenticado em qualquer página/componente. -
Suporte a execução em “Modo Desenvolvedor”, que permite login fake do OIDC (mock do
useAuth
) com base em propriedades locais do profile, evitando necessidade de um servidor OIDC IdP local. -
Hook
useToast
que fornece Toast global para que qualquer página/componente possa emitir mensagens. -
Hook
useProcessing
que fornece API para exibição de indicador de processamento (notifyStart()
enotifyStop()
), acessível em qualquer página/componente, com suporte a tratamento de requisições concorrentes. -
Suporte a timeout de request webservice via
Networking.fetch()
, que estende ofetch
do JavaScript. -
Componentes de UI complementares ao PrimeReact (
ErrorMessage
,Field
,LoadingBar
,RefreshingIcon
,RowExpansionBox
, etc).- Para aplicações móveis, o
Cloudsupport for React Native
fornece uma suite ampla de componentes de interface gráfica, que inclui tipografia, formulários, validações, mídia, popups, menus, efeitos, etc.
- Para aplicações móveis, o
Estrutura de Camadas
Os apps de frontend web possuem as seguintes camadas:
-
Camada de Apresentação
(Pages), engloba os componentes que representam as páginas web. -
Camada de Integração
(Remotes), módulos que fazem a comunicação com serviços externos, i.e., que consome os webservices dos microsserviços de backend. -
Camada de Negócio
(Services), composta por funcionalidades de negócio providas no próprio frontend web.
A camada de negócio em aplicações de frontend web tende a ser pequena ou mesmo inexistir, pois as regras de negócio são providas tipicamente pelo backend. Ela existe, por exemplo, em aplicações web que precisam oferecer funcionalidades de maneira offline utilizando o banco de dados local do browser. Ressalta-se que as regras de negócio implementadas no frontend web são passíveis, sem muito esforço, de violação, pois o código pode ser alterado pelo usuário final. É importante que todas as regras sejam sempre validadas quando enviadas para o backend. A camada de negócio em frontend web não será escopo deste manual, em razão de sua relevância reduzida, conforme mencionado.
Estrutura de Arquivos
Os apps de frontend web possuem a seguinte estrutura de pastas e arquivos:
package.json
public/
app/
O arquivo package.json
é o descritor Node do projeto. Nele é configurado o uso da
biblioteca react-cloudsupport
e frameworks associados, como o Next.js e PrimeReact.
A pasta public
é definida pelo Next.js. Seu conteúdo sugerido é:
Item | Descrição |
---|---|
favicon/ | Pasta com os arquivos de favicon para Android, iOS e web. |
resources/ | Pasta com os resources que forem necessários (imagens, scripts, CSS). |
profile.json | Arquivo definido pelo Cloudsupport que contém as propriedades da aplicação para o ambiente local. |
O profile.json
será ajustado em tempo de execução conforme as configurações de cada ambiente, como
o de teste, homologação ou produção.
A pasta app
contém o código-fonte de aplicação em aderência aos padrões do App Router do
Next.js. A estrutura sugerida para esta pasta é:
Item | Descrição |
---|---|
(pages) | Camada de apresentanção; Contém os componentes de página web. |
remotes | Camada de funcionalidades remotas; Contém os módulos para comunicação com os microsserviços de backend. |
services | Camada de negócio; Contém os componentes que implementam regras de negócio, se for o caso. |
components | Contém componentes compartilhados para uso em páginas web. |
util | Contém módulos com funções estáticas utilitárias. |
favicon.ico | Arquivo principal de favicon. |
Neste manual, o termo “componente” usualmente faz referência a componente React. O termo “módulo” faz referência a qualquer módulo JavaScript, que pode exportar constantes, objetos, funções e componentes. Cabe destacar que um componente React é também uma função, porém destinada a uso na interface gráfica, conforme ciclo de vida do React.
Diretrizes Gerais
-
Utilizar preferencialmente JavaScript puro, em conformidade com ECMAScript 6 (ES6), podendo, se for necessidade do projeto, considerar TypeScript. Este manual incluirá diretrizes e exemplos sempre baseados em JavaScript.
-
Utilizar a solução App Router do framework Next.js para organização dos componentes de página e tratamento de roteamento (navegação).
-
Preferir que funções e códigos assíncronos sejam implementados por meio de Promises em lugar da sintaxe
async/await
. -
Declarar componentes React na forma de componentes funcionais por meio da construção de funções JavaScript e uso dos Hooks. O React não recomenda a utilização de classes e orientação a objetos.
-
Evitar os operadores padrões de (des)igualdade
==
e!=
devido à complexidade da semântica IsLooselyEqual do JavaScript/TypeScript. Considerar os operadores estritos===
ou!==
e verificar explicitamente peloundefined
e pelonull
sempre que for o caso.Os operadores padrões são desencorajados devido às suas “ambiguidades” lógicas, como esta exemplificada a seguir:
a = "" b = null a == true // retorna false b == true // retorna false b == a // retorna false
Sobre loose equality: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#loose_equality_using
-
Evitar usar o operador
||
para efeito de “coalesce” ou valor padrão. Considerar??
, que é o verdadeiro Nullish coalescing operator.Exemplos:
// retorna "default" se var1 for qualquer valor Falsy (exemplo: a="" ou a=0) var1 || "default" // retorna "default" se e somente se var1 for null ou undefined var1 ?? "default"
-
Evitar implicit coercion.
Em vez de:
if (a) { // ... }
fazer:
if (a !== null && a !== undefined) { // ... }
-
Atenção aos valores Falsy no JavaScript (convertidos para false em contextos Boolean):
false
,0
,-0
,0n
,""
,null
,undefine
eNaN
.Evitar implicit coercion e os operadores
==
,!=
e||
(para fins de valor padrão) mitiga substancialmente os problemas causados pelos valores Falsy no JavaScript. -
Não utilizar a sintaxe antiga de módulos do
Node.js
, o sistema CommonJS, a citar o comandorequire()
e a variável globalmodule.exports
. Considere o padrão atual, com as diretivasimport
eexport
. -
Identar o código preferencialmente com 4 espaços e evitar o caractere de tabulação
\t
.
Convenções de Nomes
São convenções de nomes recomendadas:
Elemento | Regra |
---|---|
Pasta | CamelCase iniciando em minúsculo. |
Arquivo | CamelCase iniciando em minúsculo. |
Variáveis JavaScript | CamelCase iniciando em minúsculo. |
Constantes JavaScript | Em maiúsculo, com termos separados por _ . |
Componentes React | CamelCase iniciando em maiúsculo. |
Funções JavaScript (excetuando Componentes React) | CamelCase iniciando em minúsculo. |
Propriedades por Ambiente
A arquitetura fornece uma solução de profile, que permite definir as propriedades da aplicação por ambiente, como, por exemplo, ambiente local, teste / homologação ou produção. O profile é carregado em tempo de execução, ou seja, seria possível utilizar a mesma imagem Docker em qualquer ambiente.
As propriedades são definidas no arquivo public/profile.json
e podem ser complementadas por
JSON definido na variável de ambiente CLOUDSUPPORT_PROFILE
do sistema operacional.
O profile pode ser utilizado livremente pelo desenvolvedor para definir variáveis que devem ser ajustadas conforme o ambiente de execução.
Exemplo de profile:
{
"endpointPagamento": "https://gateway.dominio.com/api",
"chaveAcessoIntegrador": "1A938BC02F19DCCD029D94"
}
Recomenda-se evitar a parametrização da aplicação em tempo de compilação (por scripts de build-time), pois nesse caso haverá necessidade de gerar imagens Docker distintas para cada ambiente.
As propriedades são acessíveis pelo Hook useProfile()
:
const profile = useProfile();
profile.endpointPagamento; // Retorna "https://gateway.dominio.com/api"
O carregamento das propriedades de profile ocorre a partir do endpoint /.well-known/profile.json
.
Esse endpoint pode ser mapeado no arquivo next.config.js
do Next.js. O projeto do arquétipo
exemplifica a configuração.
Aviso de Atualização
O Cloudsupport for React
inclui uma funcionalidade que permite emitir aviso para o usuário
de que há atualização pendente. O aviso por padrão é um banner do topo da página, que inclui
opção para o usuário aplicar a atualização.
Exemplo:
Cabe recordar que aplicações em React são SPA (Single Page Application), tal que uma vez carregadas no browser, o usuário fará a navegação entre todas as páginas de maneira virtual, ou seja, o browser não fará a aquisição das páginas junto ao servidor web durante a navegação. Isso ocorre porque o código-fonte React (JavaScript) já foi carregado.
Se não houver um tratamento em nível de arquitetura para detecção de que o servidor web possui uma nova versão do frontend, o usuário poderá permanecer muito tempo navegando nas páginas de uma aplicação defasada, até que ocorra um refresh real ou abertura de nova janela/aba do navegador.
O Cloudsupport for React
possui um componente interno que monitora o profile, verificando
periodicamente se há mudança no retorno do endpoint /.well-known/profile.json
, como, por exemplo,
mudança na propriedade appVersion
do profile. Ocorrendo mudança, o componente emite sinal de que
a aplicação precisa ser atualizada.
Note que o processo de implantação de nova versão do frontend no ambiente de produção deve
garantir que algum campo do profile seja atualizado. Sugere-se o campo appVersion
. O projeto
de arquétipo possui um exemplo de Deployment para Kubernetes com script que injeta automaticamente o
appVersion
no profile de acordo com a tag da imagem Docker no momento da subida do Pod/container.
Próximos Passos
As seções Apresentação e Integração explanam sobre como desenvolver páginas web e como realizar a comunicação com o backend. A seção Configuração mostra como habilitar e configurar a arquitetura. Por sim, a seção Documentação da API contém a referência completa de todos os módulos e componentes da arquitetura.