Next.js e Service Workers: Guia Completo para Otimizar Seu App

Foto do autor

By luis

Os service workers são scripts que operam em segundo plano, desempenhando um papel crucial ao fornecer funcionalidades avançadas de cache e outros recursos essenciais para aplicações web contemporâneas.

Esses mecanismos transformam a experiência do usuário, assemelhando-se à fluidez e praticidade dos aplicativos nativos diretamente no navegador web.

Os service workers são, portanto, pilares na construção de Progressive Web Apps (PWAs).

Entendendo os Service Workers

Um service worker é um tipo específico de Web Worker JavaScript, executado em segundo plano e de forma independente da thread JavaScript principal. Essa separação evita bloqueios e garante que a interface do usuário do aplicativo e a interação do usuário permaneçam responsivas, sem atrasos ou interrupções.

Na prática, os service workers atuam como servidores proxy, posicionando-se entre a aplicação web e a rede. Eles têm a capacidade de interceptar requisições e respostas, armazenar recursos em cache e oferecer suporte para acesso offline. Isso resulta em aplicações web mais integradas e fáceis de usar, mesmo quando a conexão com a internet é interrompida.

Aplicações Principais para Service Workers

A versatilidade dos service workers permite seu uso em diversas situações, incluindo:

  • PWAs: Os service workers são o motor dos Progressive Web Apps, possibilitando requisições de rede customizadas, notificações push, funcionalidade offline e carregamento ágil.
  • Cache: Eles armazenam ativos do aplicativo, como imagens, código JavaScript e arquivos CSS, no cache do navegador. Isso possibilita que o navegador recupere esses elementos diretamente do cache, ao invés de solicitá-los repetidamente do servidor. O resultado é um carregamento mais rápido do conteúdo, especialmente útil em conexões de internet lentas ou instáveis.
  • Sincronização em Segundo Plano: Os service workers podem sincronizar dados e realizar outras tarefas em segundo plano, mesmo quando o usuário não está interagindo ativamente com o aplicativo ou quando ele não está aberto no navegador.

Integrando Service Workers em Aplicações Next.js

Antes de nos aprofundarmos no código, é importante compreender o ciclo de vida de um service worker, que se divide em duas fases principais: registro e ativação.

Na primeira fase, o navegador registra o service worker. Veja um exemplo básico:

const registrarServiceWorker = async () => {
    if ("serviceWorker" in navigator) {
        registro = await navigator.serviceWorker.register("/sw.js");
    }
};
registrarServiceWorker();

Este código verifica se o navegador suporta service workers, o que é comum em todos os navegadores modernos. Caso exista suporte, o código registrará um service worker, localizado no caminho de arquivo especificado.

Na fase de ativação, é necessário instalar e ativar o service worker, escutando os eventos de instalação e ativação por meio de ouvintes de eventos JavaScript. Veja como realizar essa operação:

 registro.addEventListener("install", () => {
    console.log("Service worker instalado");
});
registro.addEventListener("activate", () => {
    console.log("Service worker ativado");
});

Este código deve ser inserido logo após o registro do service worker e executado assim que o registro for concluído.

O código completo deste projeto pode ser encontrado no repositório GitHub.

Criando um Projeto Next.js

Para começar, utilize o seguinte comando para criar a estrutura básica de um projeto Next.js localmente:

npx create-next-app next-project

A adição de um service worker a um aplicativo Next.js envolve os seguintes passos:

  • Registrar o service worker no escopo global do ambiente.
  • Criar um arquivo JavaScript para o service worker no diretório público.

Adicionando um Service Worker

Primeiramente, registre o service worker. Modifique o arquivo src/pages/_app.js como descrito abaixo. A inclusão do código neste arquivo garante que o service worker seja registrado assim que o aplicativo for carregado e que tenha acesso a todos os recursos do aplicativo.

 import { useEffect } from 'react';

export default function App({ Component, pageProps }) {
    useEffect(() => {
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker
                .register('/service-worker.js', { scope: "https://www.makeuseof.com/" })
                .then((registration) => {
                    console.log(
                        'Service worker registrado com sucesso. Escopo:',
                        registration.scope
                    );
                })
                .catch((error) => {
                    console.error('Falha no registro do service worker:', error);
                });
        }
    }, []);

    return <Component {...pageProps} />;
}

O hook useEffect é acionado quando o componente é montado. Similar ao exemplo anterior, o código primeiro verifica se o navegador do usuário oferece suporte a service workers.

Se o suporte existir, ele registra o script do service worker, localizado no caminho de arquivo especificado, e define seu escopo como “/”. Isso significa que o service worker tem controle sobre todos os recursos do aplicativo. É possível definir um escopo mais específico, como “/produtos”, se necessário.

Caso o registro seja bem-sucedido, uma mensagem de confirmação, juntamente com seu escopo, será registrada. Se ocorrer um erro durante o processo, o código irá detectá-lo e exibir uma mensagem de erro.

Instalando e Ativando o Service Worker

Adicione o seguinte código a um novo arquivo, public/service-worker.js.

const eventoInstalar = () => {
    self.addEventListener('install', () => {
        console.log('service worker instalado!!!!');
    });
};
eventoInstalar();
    
const eventoAtivar = () => {
    self.addEventListener('activate', () => {
        console.log('service worker ativado!!!');
    });
};

eventoAtivar();

Para confirmar o registro, instalação e ativação bem-sucedida do service worker, inicie o servidor de desenvolvimento e abra o aplicativo no navegador.

npm run dev

Abra a janela Ferramentas do desenvolvedor do Chrome (ou equivalente em seu navegador) e acesse a aba “Aplicativo”. Na seção “Service Workers”, você poderá ver o service worker que você registrou.

Com o service worker registrado, instalado e ativado com sucesso, você pode começar a implementar funcionalidades como cache, sincronização em segundo plano ou envio de notificações push.

Armazenando Recursos em Cache com Service Workers

O armazenamento em cache dos ativos do aplicativo no dispositivo do usuário pode otimizar o desempenho, permitindo acesso mais rápido aos recursos, especialmente em situações com conexões de internet instáveis.

Para armazenar os ativos do aplicativo em cache, insira o código a seguir no arquivo service-worker.js.

const nomeCache="teste-cache";

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((respostaCache) => {
            return respostaCache || fetch(event.request).then((resposta) => {
                return caches.open(nomeCache).then((cache) => {
                    cache.put(event.request, resposta.clone());
                    return resposta;
                });
            });
        })
    );
});

Ao acessar a página inicial pela primeira vez, esse código verifica se existe uma resposta em cache para a requisição. Caso a resposta em cache seja encontrada, o service worker a retorna ao cliente.

Caso a resposta em cache não exista, o service worker busca o recurso do servidor através da rede, fornecendo a resposta ao cliente e armazenando-a em cache para requisições futuras.

Para visualizar os ativos armazenados em cache, abra a aba “Aplicativo” nas ferramentas do desenvolvedor. Na seção “Armazenamento em cache”, você deverá encontrar uma lista dos ativos que foram armazenados em cache. É possível também marcar a opção “Offline” na seção “Service Worker” e recarregar a página para simular uma experiência offline.

Agora, após visitar a página inicial, o navegador utilizará os recursos armazenados em cache, ao invés de solicitar dados da rede.

Utilizando Service Workers para Otimizar o Desempenho

Os service workers representam uma ferramenta eficaz para aprimorar o desempenho de aplicações Next.js. Através do armazenamento em cache de recursos, interceptação de requisições e oferecimento de suporte offline, a experiência do usuário é significativamente melhorada.

É importante salientar, no entanto, que a implementação e gestão de service workers podem apresentar certa complexidade. É crucial analisar cuidadosamente os potenciais benefícios e desvantagens antes de decidir utilizá-los.