Ativar os workers de serviço para informar aos navegadores quais páginas funcionam off-line
O que é a API Content Indexing?
Usar um Progressive Web App significa ter acesso a informações importantes para as pessoas, como imagens, vídeos, artigos e muito mais, independentemente do estado atual da sua conexão de rede. Tecnologias como service workers, a API Cache Storage e o IndexedDB fornecem os blocos de construção para armazenar e fornecer dados quando as pessoas interagem diretamente com um PWA. No entanto, criar um PWA de alta qualidade e que prioriza o modo off-line é apenas parte da história. Se as pessoas não perceberem que o conteúdo de um app da Web está disponível enquanto elas estão off-line, elas não vão aproveitar ao máximo o trabalho que você fez para implementar essa funcionalidade.
Esse é um problema de descoberta. Como seu PWA pode informar os usuários sobre o conteúdo compatível com modo off-line para que eles possam descobrir e visualizar o que está disponível? A API Content Indexing é uma solução para esse problema. A parte voltada ao desenvolvedor dessa solução é uma extensão para service workers, que permite aos desenvolvedores adicionar URLs e metadados de páginas off-line a um índice local mantido pelo navegador. Essa melhoria está disponível no Chrome 84 e em versões mais recentes.
Quando o índice for preenchido com conteúdo do seu PWA e de outros PWAs instalados, ele será exibido pelo navegador, conforme mostrado abaixo.
Além disso, o Chrome pode recomendar conteúdo de forma proativa quando detecta que um usuário está off-line.
A API Content Indexing não é uma maneira alternativa de armazenar conteúdo em cache. É uma maneira de fornecer metadados sobre páginas que já estão armazenadas em cache pelo worker do serviço para que o navegador possa mostrar essas páginas quando as pessoas provavelmente quiserem acessar. A API Content Indexing ajuda na possibilidade de descoberta de páginas em cache.
Confira na prática
A melhor maneira de ter uma noção sobre a API de indexação de conteúdo é testar um aplicativo de exemplo.
- Verifique se você está usando um navegador e uma plataforma compatíveis. No momento,
essa opção está limitada ao Chrome 84 ou mais recente no Android. Acesse
about://version
para conferir qual versão do Chrome você está usando. - Acesse https://contentindex.dev.
- Clique no botão
+
ao lado de um ou mais itens da lista. - (Opcional) Desative o Wi-Fi e a conexão de dados móveis do dispositivo ou ative o modo avião para simular a desconexão do navegador.
- Escolha Downloads no menu do Chrome e mude para a guia Artigos para você.
- Navegue pelo conteúdo que você salvou anteriormente.
Veja o código-fonte do aplicativo de exemplo no GitHub (link em inglês).
Outro aplicativo de exemplo, um Scrapbook PWA, ilustra o uso da API Content Indexing com a API Web Share Target. O código demonstra uma técnica para manter a API Content Indexing sincronizada com os itens armazenados por um app da Web usando a API Cache Storage.
Como usar a API
Para usar a API, seu app precisa ter um service worker e URLs que possam ser navegáveis off-line. Se o app da Web não tiver um service worker, as bibliotecas do Workbox podem simplificar a criação dele.
Que tipo de URL pode ser indexado como compatível off-line?
A API oferece suporte à indexação de URLs correspondentes a documentos HTML. Por exemplo, um URL de um arquivo de mídia em cache não pode ser indexado diretamente. Em vez disso, você precisa fornecer um URL para uma página que mostre mídia e funcione off-line.
Um padrão recomendado é criar uma página HTML "visualizador" que possa aceitar o URL da mídia como um parâmetro de consulta e mostrar o conteúdo do arquivo, possivelmente com controles ou conteúdo adicionais na página.
Os apps da Web só podem adicionar URLs ao índice de conteúdo que estão no escopo do worker de serviço atual. Em outras palavras, um app da Web não poderia adicionar ao índice de conteúdo um URL pertencente a um domínio completamente diferente.
Visão geral
A API Content Indexing oferece suporte a três operações: adicionar, listar e
remover metadados. Esses métodos são expostos de uma nova propriedade, index
, que
foi adicionada à
interface
ServiceWorkerRegistration
.
A primeira etapa para indexar conteúdo é receber uma referência ao
ServiceWorkerRegistration
atual. Usar navigator.serviceWorker.ready
é a maneira mais simples:
const registration = await navigator.serviceWorker.ready;
// Remember to feature-detect before using the API:
if ('index' in registration) {
// Your Content Indexing API code goes here!
}
Se você estiver fazendo chamadas para a API Content Indexing em um service worker,
em vez de dentro de uma página da Web, poderá se referir ao ServiceWorkerRegistration
diretamente pelo registration
. Ele já será definido
como parte do ServiceWorkerGlobalScope.
.
Como adicionar à indexação
Use o método add()
para indexar URLs e os metadados associados. Você
escolhe quando os itens são adicionados ao índice. Talvez você queira adicionar ao
índice em resposta a uma entrada, como clicar no botão "salvar off-line". Ou
você pode adicionar itens automaticamente sempre que os dados armazenados em cache forem atualizados por um mecanismo
como a sincronização em segundo plano periódica.
await registration.index.add({
// Required; set to something unique within your web app.
id: 'article-123',
// Required; url needs to be an offline-capable HTML page.
url: '/articles/123',
// Required; used in user-visible lists of content.
title: 'Article title',
// Required; used in user-visible lists of content.
description: 'Amazing article about things!',
// Required; used in user-visible lists of content.
icons: [{
src: '/img/article-123.png',
sizes: '64x64',
type: 'image/png',
}],
// Optional; valid categories are currently:
// 'homepage', 'article', 'video', 'audio', or '' (default).
category: 'article',
});
A adição de uma entrada afeta apenas o índice de conteúdo. Ela não adiciona nada ao cache.
Caso extremo: chame add()
do contexto window
se os ícones dependerem de um gerenciador fetch
Quando você chama add()
, o Chrome faz uma solicitação para
o URL de cada ícone, garantindo que ele tenha uma cópia do ícone a ser usada ao
exibir uma lista de conteúdo indexado.
Se você chamar
add()
do contextowindow
(ou seja, da sua página da Web), essa solicitação vai acionar um eventofetch
no service worker.Se você chamar
add()
no service worker (talvez dentro de outro manipulador de eventos), a solicitação não vai acionar o manipuladorfetch
do service worker. Os ícones serão buscados diretamente, sem a participação de nenhum worker de serviço. Considere isso se os ícones dependerem do gerenciadorfetch
, talvez porque eles existam apenas no cache local e não na rede. Se for o caso, chame apenasadd()
do contextowindow
.
Como listar o conteúdo do índice
O método getAll()
retorna uma promessa para uma lista iterável de entradas indexadas e os respectivos metadados. As entradas retornadas vão conter todos os dados salvos com
add()
.
const entries = await registration.index.getAll();
for (const entry of entries) {
// entry.id, entry.launchUrl, etc. are all exposed.
}
Como remover itens do índice
Para remover um item do índice, chame delete()
com o id
do item a ser
excluído:
await registration.index.delete('article-123');
Chamar delete()
afeta apenas o índice. Ele não exclui nada do
cache.
Como processar um evento de exclusão de usuário
Quando o navegador mostra o conteúdo indexado, ele pode incluir a própria interface de usuário com um item de menu Excluir, às pessoas a chance de indicar que elas terminaram de visualizar o conteúdo indexado anteriormente. Confira como a interface de exclusão parece no Chrome 80:
Quando alguém seleciona esse item de menu, o worker de serviço do app da Web recebe
um evento contentdelete
. Embora o processamento desse evento seja opcional, ele oferece uma
chance para que o worker de serviço "limpe" o conteúdo, como arquivos de mídia em cache local, que alguém indicou que não vai mais usar.
Não é necessário chamar registration.index.delete()
no gerenciador
contentdelete
. Se o evento foi acionado, a exclusão de índice
relevante já foi realizada pelo navegador.
self.addEventListener('contentdelete', (event) => {
// event.id will correspond to the id value used
// when the indexed content was added.
// Use that value to determine what content, if any,
// to delete from wherever your app stores it—usually
// the Cache Storage API or perhaps IndexedDB.
});
Feedback sobre o design da API
Há algo na API que é estranho ou não funciona como esperado? Ou há partes que faltam para implementar sua ideia?
Envie um problema no repositório do GitHub sobre a API Content Indexing ou adicione sua opinião a um problema existente.
Problemas com a implementação?
Você encontrou um bug na implementação do Chrome?
Registre um bug em https://new.crbug.com. Inclua o máximo
de detalhes possível, instruções simples para reprodução e defina Components
como Blink>ContentIndexing
.
Planeja usar a API?
Planejando usar a API de indexação de conteúdo no seu app da Web? Seu apoio público ajuda o Chrome a priorizar recursos e mostra a outros fornecedores de navegadores como é essencial oferecer suporte a eles.
- Envie um tweet para @ChromiumDev usando a hashtag
#ContentIndexingAPI
e detalhes sobre onde e como você está usando.
Quais são algumas implicações de segurança e privacidade da indexação de conteúdo?
Confira as respostas fornecidas em resposta ao questionário de segurança e privacidade do W3C. Se você tiver outras dúvidas, inicie uma discussão no repositório do GitHub do projeto.
Imagem principal de Maksym Kaharlytskyi no Unsplash.