Construindo um PWA usando Angular 6
Publicados: 2022-03-10 Neste tutorial, usaremos o Angular 6 mais recente para construir um PWA implementando os princípios básicos que fazem um PWA. Começaremos criando um aplicativo web front-end que consome uma API JSON. Para isso, usaremos o módulo Angular HttpClient
para enviar solicitações HTTP para uma API JSON estática gerada a partir do repositório GitHub Simplified JavaScript Jargon. Também usaremos o Material Design para construir a interface do usuário por meio do pacote Angular Material.
Em seguida, usaremos o painel “Audits” (Lighthouse) do Chrome DevTools para analisar nosso aplicativo da Web em relação aos princípios básicos dos PWAs. Por fim, explicaremos e adicionaremos os recursos do PWA ao nosso aplicativo da Web de acordo com a seção “Progressive Web App” no relatório do Lighthouse.
Antes de começarmos a implementar nosso PWA, vamos primeiro apresentar os PWAs e o Lighthouse.
Leitura recomendada : Native And PWA: Choices, Not Challengers!
O que é um PWA?
Um Progressive Web App ou PWA é um aplicativo da Web que possui um conjunto de recursos (semelhantes aos aplicativos nativos) que fornecem uma experiência semelhante a um aplicativo aos usuários. Os PWAs precisam atender a um conjunto de requisitos essenciais que veremos a seguir. Os PWAs são semelhantes aos aplicativos nativos, mas são implantados e acessíveis a partir de servidores da Web por meio de URLs, portanto, não precisamos passar pelas lojas de aplicativos.
Um PWA precisa ser:
- Progressivo
Trabalhe para todos os usuários, independentemente da escolha do navegador, porque eles são construídos com aprimoramento progressivo como um princípio central. - Responsivo
Adapta-se a qualquer formato, desktop, celular, tablet ou o que vier a seguir. - Independente de conectividade
Aprimorado com service workers para trabalhar offline ou em redes de baixa qualidade. - Tipo aplicativo
Use o modelo app-shell para fornecer navegação e interações no estilo de aplicativo. - Fresco
Sempre atualizado graças ao processo de atualização do service worker. - Seguro
Servido via HTTPS para evitar espionagem e garantir que o conteúdo não tenha sido adulterado. - Detectável
São identificáveis como “aplicativos” graças aos manifestos do W3C e ao escopo de registro do service worker, permitindo que os mecanismos de pesquisa os encontrem. - Reativável
Facilite o reengajamento por meio de recursos como notificações push. - Instalável
Permita que os usuários “mantenham” os aplicativos que consideram mais úteis na tela inicial sem o incômodo de uma loja de aplicativos. - Linkável
Compartilhe facilmente via URL e não exija instalação complexa.
Apresentando o Farol
O Lighthouse é uma ferramenta de auditoria de código aberto criada pelo Google que pode ser usada para auditar sites e aplicativos quanto ao desempenho de acessibilidade, SEO, práticas recomendadas e recursos de PWA.
Você pode acessar o Lighthouse na guia Auditoria no Chrome DevTools como um módulo no Node.js ou como uma ferramenta CLI. Você pode usar o Lighthouse fornecendo um URL e, em seguida, executando as auditorias que fornecerão um relatório contendo os resultados da auditoria, que são basicamente sugestões sobre como você pode melhorar seu aplicativo da web.
Instalando o Angular CLI v6 e gerando um projeto
Nesta seção, instalaremos a versão mais recente do Angular CLI e a usaremos para criar um novo projeto Angular 6.
A CLI Angular requer Node.js >= 8.9+ , portanto, primeiro verifique se você tem a versão necessária instalada executando o seguinte comando:
$ node -v
Caso você não tenha o Node.js instalado, você pode simplesmente acessar a página oficial de download do Node e pegar os binários do Node para o seu sistema.
Agora, você pode instalar a versão mais recente do Angular CLI executando:
$ npm install -g @angular/cli
Nota : Dependendo da configuração do npm, pode ser necessário adicionar _sudo_
para instalar pacotes globalmente.
Você pode gerar seu projeto Angular 6 executando o seguinte comando em seu terminal:
$ ng new pwademo
Isso criará um projeto com uma estrutura que se parece com:
A maior parte do trabalho feito estará dentro da pasta src/
que contém o código-fonte do aplicativo.
Criando o aplicativo angular
Depois de gerar um projeto, vamos construir uma aplicação web que consome uma API JSON e exibe os itens na página inicial. Usaremos o serviço HttpClient para enviar solicitações HTTP e Angular Material para construir a interface do usuário.
Adicionando Material Angular
Graças ao Angular CLI v6 e ao novo comando ng add , adicionar Angular Material ao seu projeto está a apenas um comando de distância. Você só precisa executar o seguinte comando no seu terminal:
$ cd pwademo $ ng add @angular/material
Você pode ver na captura de tela que o comando instala o pacote necessário do npm e atualiza vários arquivos para configurar o Angular Material em seu projeto que anteriormente precisava de atualizações manuais.
Configurando o HttpClient
e consumindo a API JSON
Agora, vamos configurar o projeto Angular para usar HttpClient
para enviar solicitações HTTP. Primeiro, você precisa importar o módulo HttpClientModule
no módulo principal do aplicativo no arquivo src/app/app.module.ts
:
/*...*/ import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
É isso. Agora podemos injetar e usar HttpClient
em qualquer componente ou serviço que pertença ao módulo principal.
Para fins de demonstração, consumiremos uma API JSON gerada estaticamente do repositório Simplified JavaScript Jargon GitHub. Se você estiver consumindo qualquer outro recurso, certifique-se de ter o CORS habilitado para que o navegador não impeça a leitura do recurso remoto devido à Política de Mesma Origem .
Vamos criar um serviço que faça interface com a API. Dentro da pasta do seu projeto, execute:
$ ng g service api
Isso criará um serviço chamado ApiService
no arquivo src/app/api.service.ts
.
Agora abra o arquivo src/app/api.service.ts
e atualize-o para refletir as seguintes alterações:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export interface Item{ name: string; description: string; url: string; html: string; markdown: string; } @Injectable({ providedIn: 'root' }) export class ApiService { private dataURL: string = "https://www.techiediaries.com/api/data.json"; constructor(private httpClient: HttpClient) {} fetch(): Observable<Item[]>{ return <Observable<Item[]>this.httpClient.get(this.dataURL); } }
Primeiro importamos as classes HttpClient
e Observable
, em seguida, injetamos o HttpClient
no construtor como httpClient
e adicionamos um método fetch()
que chama o método get()
de HttpClient
(para enviar uma solicitação HTTP GET para nosso endpoint JSON) e retorna um Observable que podemos assinar mais tarde.
Também declaramos uma interface Item
que representa um único item dos dados JSON retornados.
Em seguida, importe este serviço do componente do aplicativo. Abra o arquivo src/app/app.component.ts
e adicione:
import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; import { Item } from './api.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ title = 'pwademo'; items: Array<Item>; constructor(private apiService: ApiService){ } ngOnInit(){ this.fetchData(); } fetchData(){ this.apiService.fetch().subscribe((data: Array<Item>)=>{ console.log(data); this.items = data; }, (err)=>{ console.log(err); }); } }
Importamos o ApiService
que criamos antes e injetamos como apiService
, também importamos a classe Item
que representa um único item de nossos dados JSON e declaramos a variável items
do tipo Array<Item>
que conterá os itens buscados.
Em seguida, adicionamos um método fetchData()
que chama nosso método fetch()
que definimos no ApiService
que retorna um Observable. Simplesmente assinamos esse observável para enviar uma solicitação GET ao nosso endpoint JSON e obter os dados de resposta que finalmente atribuímos à matriz de items
.
Chamamos o método ngOnInit()
fetchData()
evento de ciclo de vida ngOnInit() para que ele seja chamado assim que o componente AppComponent
for inicializado.
Adicionando a IU do aplicativo
Nossa interface do aplicativo consistirá em uma barra de navegação e no esqueleto da página que será criada com o Angular Material.
Antes de usar um componente Angular Material, você precisará importar seu módulo. Cada componente Material pertence ao seu próprio módulo.
Abra o arquivo src/app/app.module.ts
e adicione as seguintes importações:
/*...*/ import { MatToolbarModule } from '@angular/material/toolbar'; import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ MatToolbarModule, MatCardModule, MatButtonModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Importamos módulos para componentes de barra de ferramentas, cartão e botão e os adicionamos ao array imports do AppModule
.
Em seguida, abra o arquivo src/app/app.component.html
, exclua o que está lá e adicione:
<mat-toolbar color="primary"> <mat-toolbar-row> <span>JS-jargon</span> </mat-toolbar-row> </mat-toolbar> <main> <mat-card *ngFor="let item of items"> <mat-card-header> <mat-card-title>{{item.name}}</mat-card-title> </mat-card-header> <mat-card-content> {{item.description}} </mat-card-content> <mat-card-actions> <a mat-raised-button href="{{item.url}}" color="primary">More</a> </mat-card-actions> </mat-card> </main>
Usamos componentes de material para criar a interface do usuário. O componente <mat-toolbar>
é usado para criar uma barra de ferramentas de material e o componente <mat-card>
é usado para criar um cartão de material etc.
Nós iteramos sobre a matriz de items
que é preenchida pelo método fetchData()
quando o componente é inicializado e exibimos os itens como cartões de material. Cada cartão contém o nome, a descrição e um link para mais informações (o link tem o estilo de um botão Material usando a diretiva mat-raised-button
).
Esta é uma captura de tela do aplicativo:
Construindo o aplicativo para produção
Normalmente, ao verificar se há recursos do PWA em seu aplicativo, você deve primeiro compilá-lo para produção, pois a maioria dos recursos do PWA não é adicionada no desenvolvimento. Por exemplo, você não deseja ter service workers e cache habilitados no desenvolvimento, pois você precisará atualizar os arquivos periodicamente.
Vamos construir o aplicativo para produção usando o seguinte comando:
$ ng build --prod
A compilação de produção estará disponível na pasta dist/pwademo
. Podemos usar uma ferramenta como http-server
para servi-lo.
Primeiro, instale http-server
usando o seguinte comando:
$ npm i -g http-server
Você pode então executá-lo usando o seguinte comando:
$ cd dist/pwademo $ http-server -o
A opção -o
abrirá automaticamente o navegador padrão em seu sistema e navegará até o endereço https://127.0.0.1:8080/
onde nosso aplicativo da web está disponível.
Analisando o aplicativo usando o Lighthouse
Vamos agora analisar nosso aplicativo usando o Lighthouse. Primeiro, inicie o Chrome e visite o endereço do nosso aplicativo https://127.0.0.1:8080/
.
Em seguida, abra as Ferramentas do desenvolvedor ou pressione Ctrl + Shift + I e clique no painel Auditoria .
De preferência, você precisa definir a Emulação como Móvel em vez de Desktop para emular um ambiente móvel. Em seguida, clique em Executar uma auditoria… botão azul. Você terá uma caixa de diálogo aberta na qual precisa escolher os tipos de auditorias que deseja realizar em seu aplicativo da web. Desmarque todos os tipos, exceto o Progressive Web App , e clique no botão Executar auditoria .
Aguarde o Lighthouse gerar o relatório. Esta é uma captura de tela do resultado nesta fase:
O Lighthouse executa uma série de verificações que validam os aspectos de um Progressive Web App especificados pela Lista de verificação do PWA. Obtemos uma pontuação inicial de 36 ⁄ 100 porque temos algumas auditorias aprovadas.
Nosso aplicativo tem 7 auditorias com falha principalmente relacionadas a Service Workers , Progressive Enhancement , HTTPS e Web App Manifest que são os principais aspectos de um PWA.
Registrando um Service Worker
As duas primeiras auditorias com falha (“Não registra um service worker” e “Não responde com 200 quando offline”) estão relacionadas a Service Workers e armazenamento em cache. Então, o que é um trabalhador de serviço?
Um service worker é um recurso disponível em navegadores modernos que pode ser usado como um proxy de rede que permite que seu aplicativo intercepte solicitações de rede para armazenar ativos e dados em cache. Isso pode ser usado para implementar recursos do PWA, como suporte offline e notificações por push, etc.
Para passar nessas auditorias, basta registrar um service worker e usá-lo para armazenar arquivos em cache localmente. Quando offline, o SW deve retornar a versão do arquivo armazenada em cache localmente. Veremos um pouco mais tarde como adicionar isso com um comando CLI.
Leitura recomendada : Fazendo um trabalhador de serviço: um estudo de caso
Aprimoramento progressivo
A terceira auditoria com falha (“Não fornece conteúdo de fallback quando o JavaScript não está disponível”) está relacionada ao Aprimoramento Progressivo, que é um aspecto essencial de um PWA e simplesmente se refere à capacidade dos PWAs de serem executados em diferentes navegadores, mas fornecer recursos avançados se eles estão disponíveis. Um exemplo simples de PE é o uso da tag HTML <noscript>
que informa aos usuários a necessidade de habilitar o JavaScript para executar a aplicação caso não esteja habilitado:
<noscript> Please enable JavaScript to run this application. </noscript>
HTTPS
A quarta auditoria com falha (“Não redireciona o tráfego HTTP para HTTPS”) está relacionada ao HTTPS, que também é um aspecto central dos PWAs (os service workers só podem ser atendidos de origens seguras, exceto localhost). A auditoria “Usa HTTPS” em si é considerada aprovada pelo Lighthouse, pois estamos auditando o host local, mas quando você usa um host real, precisa de um certificado SSL. Você pode obter um certificado SSL gratuito de diferentes serviços, como Let's Encrypt, Cloudflare, Firebase ou Netlify etc.
O manifesto do aplicativo da Web
As três auditorias com falha ("O usuário não será solicitado a instalar o aplicativo da Web", "Não está configurado para uma tela inicial personalizada" e "A barra de endereço não corresponde às cores da marca") estão relacionadas a um manifesto de aplicativo da Web ausente, que é um arquivo no formato JSON que fornece o nome, descrição, ícones e outras informações exigidas por um PWA. Ele permite que os usuários instalem o aplicativo da Web na tela inicial como aplicativos nativos sem passar por uma loja de aplicativos.
Você precisa fornecer um manifesto de aplicativo da Web e referenciá-lo a partir do arquivo index.html
usando uma tag <link>
com a propriedade rel
definida como manifest
. Veremos a seguir como podemos fazer isso automaticamente com um comando CLI.
Implementando recursos de PWA
Angular CLI v6 permite que você adicione rapidamente recursos de PWA a um aplicativo Angular existente. Você pode transformar seu aplicativo em um PWA simplesmente executando o seguinte comando em seu terminal a partir da raiz do projeto:
$ ng add @angular/pwa
O comando adiciona automaticamente recursos do PWA ao nosso aplicativo Angular, como:
- Um arquivo
manifest.json
, - Diferentes tamanhos de ícones na pasta
src/assets/icons
, - O service worker
ngsw-worker.js
.
Abra a pasta dist/
que contém a compilação de produção. Você encontrará vários arquivos, mas vamos nos concentrar nos arquivos relacionados aos recursos do PWA que mencionamos acima:
Um arquivo manifest.json
foi adicionado com o seguinte conteúdo:
{ "name": "pwademo", "short_name": "pwademo", "theme_color": "#1976d2", "background_color": "#fafafa", "display": "standalone", "scope": "/", "start_url": "/", "icons": [ { "src": "assets/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "assets/icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "assets/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "assets/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "assets/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "assets/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "assets/icons/icon-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "assets/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] }
Como você pode ver, o arquivo manifest.json
adicionado possui todas as informações exigidas por um PWA, como nome, descrição e start_url
etc.
O arquivo manifest.json
, links para ícones com tamanhos diferentes, que também foram adicionados automaticamente na pasta assets/icons
. Obviamente, você precisará alterar esses ícones com os seus próprios quando estiver pronto para criar a versão final do seu PWA.
No arquivo index.html
, o arquivo manifest.json
é referenciado usando:
<link rel="manifest" href="manifest.json">
Também foi adicionado automaticamente o arquivo ngsw-worker.js
, que contém o service worker. O código para instalar este service worker é inserido automaticamente no arquivo src/app/app.module.ts
:
... import { ServiceWorkerModule } from '@angular/service-worker'; @NgModule({ declarations: [ AppComponent ], imports: [ ... ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) ],
O @angular/service-worker
é instalado pelo comando ng add
e adicionado como uma dependência ao pwademo/package.json
:
"dependencies": { ... "@angular/service-worker": "^6.1.0" }
O suporte à construção do service worker também está habilitado na CLI. No arquivo angular.json
uma opção de configuração "serviceWorker": true
é adicionada.
No arquivo index.html
é adicionada uma meta tag para theme-color
com um valor de #1976d2
(também corresponde ao valor theme_color
no arquivo manifest.json
):
<meta name="theme-color" content="#1976d2">
A cor do tema informa ao navegador qual cor pintar os elementos da interface do usuário, como a barra de endereço.
Adicionar a cor do tema aos arquivos index.html
e manifest.json
corrige a auditoria Address Bar Matches Brand Colors.
O arquivo de configuração do Service Worker
Outro arquivo src/ngsw-config.json
é adicionado ao projeto, mas não é um arquivo necessário para PWAs. É um arquivo de configuração que permite especificar quais arquivos e URLs de dados o service worker Angular deve armazenar em cache e como ele deve atualizar os arquivos e dados armazenados em cache. Você pode encontrar todos os detalhes sobre este arquivo nos documentos oficiais.
Nota : Até o momento, com a última versão 6.1.3 anterior, o comando ng add @angular/pwa
falhará com este erro: Path “/ngsw-config.json” already exists
, então, por enquanto, a solução é fazer o downgrade de @angular/cli
e @angular/pwa
para a versão 6.0.8 .
Basta executar os seguintes comandos em seu projeto:
$ npm i @angular/[email protected] $ ng i @angular/[email protected] $ ng add @angular/pwa
Agora vamos executar novamente as auditorias em nosso PWA local hospedado localmente. Esta é a nova pontuação do PWA:
A CLI Angular não adiciona automaticamente o código de fallback JavaScript que mencionamos na seção Progressive Enhancement, então abra o arquivo src/index.html
e adicione-o:
<noscript> Please enable JavaScript to run this application. </noscript>
Em seguida, reconstrua seu aplicativo e execute novamente as auditorias. Este é o resultado agora:
Temos apenas uma auditoria com falha relacionada ao redirecionamento HTTPS. Precisamos hospedar o aplicativo e configurar o redirecionamento HTTP para HTTPS.
Vamos agora executar as auditorias em uma versão hospedada e segura do nosso PWA.
Obtemos uma pontuação de 100 ⁄ 100 , o que significa que implementamos com sucesso todos os princípios básicos dos PWAs.
Você pode obter o código final deste PWA de demonstração neste repositório do GitHub.
Conclusão
Neste tutorial, criamos um aplicativo Angular simples e o transformamos em um PWA usando a CLI Angular. Usamos o Lighthouse do Google para auditar nosso aplicativo quanto aos recursos de PWA e explicamos vários princípios básicos de PWAs, como Service Workers para adicionar suporte offline e notificações push. O arquivo de manifesto da Web para habilitar recursos de adição à tela inicial e tela inicial, aprimoramento progressivo e HTTPS .
Você também pode precisar verificar manualmente outros itens destacados (na seção "Itens adicionais para verificar manualmente"), mas não verificados automaticamente pelo Lighthouse. Essas verificações são exigidas pela lista de verificação de PWA básica do Google. Eles não afetam a pontuação do PWA, mas é importante que você os verifique manualmente. Por exemplo, você precisa garantir que seu site funcione em vários navegadores e que cada página tenha uma URL importante para fins de compartilhamento nas mídias sociais.
Como os PWAs também tratam de outros aspectos, como melhor desempenho e acessibilidade percebidos, você também pode usar o Lighthouse para auditar seu PWA (ou qualquer site geral) para esses aspectos e melhorá-lo conforme necessário.