Maximizar a taxa de acertos do cache

Uma das melhores formas de melhorar o desempenho de sua loja (virtual) é maximizar a taxa de acertos do cache. Qualquer solicitação que possa ser atendida proveniente do cache da CDN do Managed Runtime conta como acerto do cache. Com cada acerto do cache, você agiliza o carregamento de páginas para o usuário porque elimina a necessidade de renderizar essa página no lado do servidor e de fazer quaisquer solicitações aos sistemas e as APIs de back-end.

Este guia cobre três técnicas distintas para aumentar os acertos do cache: configuração de durações ótimas do cache, renderização condicional e filtragem de strings de consulta. Vejamos cada técnica em detalhes.

A duração ótima para guardar uma solicitação HTTP em cache depende do que está sendo solicitado. Uma solicitação para carregar uma página de conteúdo que raramente se modifica pode ser guardada em cache com total segurança por muito tempo. Já uma página de listagem de produtos que é atualizada com frequência com novos produtos pode exigir uma duração do cache mais curta, como 15 minutos. Sempre que possível, escolha durações mais longas para maximizar a taxa de acertos do cache.

Um cabeçalho de controle de cache na resposta HTTP determina a duração que uma resposta à solicitação de uma página é armazenada no cache de CDN. Por padrão, a duração do cache para respostas a páginas em um projeto do PWA Kit é de 600 segundos (ou seja, 10 minutos). Você pode personalizar a duração do cache por página ou para todas as páginas.

Para ver mais informações gerais sobre cache, recomendamos este artigo do Google: Prevent unnecessary network requests with the HTTP Cache (Prevenir solicitações desnecessárias com cache HTTP).

A função getProps de qualquer componente de página permite que você personalize a resposta HTTP usando um objeto que é transmitido denominado res. Para definir a duração de cache de uma página, use o método set do objeto res para definir um cabeçalho Cache-Control e especifique um valor em segundo para a diretiva max-age.

Por exemplo, este componente ProductList amplia a duração do cache do padrão de 600 segundos para 900 segundos:

Não recomendamos definir um cabeçalho de controle de cache na função getProps que pertence ao componente especial App definido em app/components/_app/index.jsx. As funções getProps tanto para o componente App quanto para o componente da página atual são executados ao mesmo tempo. Essa execução paralela leva a resultados imprevisíveis se você definir o mesmo cabeçalho de resposta em ambas as funções.

Você pode definir a duração do cache para todas as páginas em app/ssr.js. Você pode modificar a duração do cache padrão ao definir uma novo valor para defaultCacheTimeSeconds. Caso necessite de um maior controle do cabeçalho HTTP, adicione o manipulador Express que define um cabeçalho personalizado, como nesse exemplo:

Você pode comprovar se os controles do cache estão presentes nos cabeçalhos de resposta ao inspecionar suas solicitações de rede com o DevTools do Chrome na guia Network (Rede). Você também pode executar o seguinte comando curl em seu terminal, que mostra todos os cabeçalhos de resposta. Substitua <URL> no comando de exemplo pelo URL completo que você deseja testar, incluindo qualquer string de consulta necessária.

Para garantir que uma página seja adequada para cache pela CDN, você deve adicionar código condicional para evitar a renderização dos seguintes tipos de conteúdo no lado do servidor:

  • Conteúdo personalizado, como nome de usuário, o número de itens no carrinho e o método de pagamento preferido. O conteúdo personalizado não é adequado, tampouco relevante para qualquer pessoa que não seja um usuário único. Respostas em cache para um usuário único não aumenta os acertos de cache.
  • Conteúdo modificado com frequência, como preços de produtos, inventário restante ou promoções. Esse tipo de conteúdo não é adequado para cache porque há o risco de confundir o usuário quando a página contém informações já desatualizadas.

Pense na página que é renderizada no lado do servidor como uma base genérica para que o cliente a desenvolva. Depois de carregar rapidamente a versão da página do lado do servidor no dispositivo do usuário, o navegador renderiza o conteúdo, que é personalizado e constantemente modificado.

Para determinar se a renderização está acontecendo no lado do cliente ou do servidor, verifique a existência do objeto window, que só está presente no lado do cliente. O exemplo a seguir usa essa técnica para renderizar um preço somente no lado do cliente:

Para ver em seu navegador a versão da página que é renderizada no lado do servidor, anexe ?__server_only ao URL. Esse parâmetro de consulta interrompe o processo de hidratação para que o navegador não assuma a renderização, deixando a página intocada depois da renderização do lado do servidor.

A maioria dos aplicativos de lojas (virtuais) usa a string de consulta de um URL para armazenar parâmetros e valores que representam aspectos do estado do aplicativo. Por exemplo, quando um usuário busca “suéteres,” você pode incluir o termo de pesquisa na string de consulta. Dessa maneira: ?search=sweaters. As strings de consulta são comumente usadas para rastrear as ações do usuário. Por exemplo, podemos anexar uma string de consulta exclusiva a cada link em um e-mail para rastrear as interações com ele: user=juanita&source=email.

Nem todos os parâmetros da string de consulta são relevantes no que se diz respeito ao cache. O Managed Runtime inclui a função de borda chamada request processor (processador de solicitação), que permite modificar a string de consulta de uma solicitação antes que ela busque respostas em cache. Você pode aumentar os acertos de cache ao usar o processador de solicitação para associar URLs similares à mesma resposta em cache.

Para personalizar o processador de solicitação, edite a função processRequest definida em app/request-processor.js.

O exemplo a seguir define um processador de solicitação que filtra os parâmetros gclid e utm_campaign da string de consulta. Esses parâmetros são comumente associados com as campanhas de marketing do Google e só são uteis no lado do cliente. Para simplificar o trabalho com as strings de consulta, a classe QueryParameters do PWA Kit React SDK é importada.

O URL completo que é usado para buscar o objeto correspondente no cache inclui a versão da string de consulta que é retornada pelo processador de solicitação. Se não houver resposta em cache para esse URL, essa mesma versão modificada do URL é transmitida para o aplicativo Express.

Atenção a duas possíveis “pegadinhas” ao usar essa abordagem:

Primeiro, certifique-se de que seu aplicativo não dependa de nenhum parâmetro filtrado para a renderização. Por exemplo, se você filtrou o parâmetro search do exposto acima, vai ser difícil poder exibir os resultados de pesquisa corretos.

Segundo, cuidado ao filtrar os parâmetros das solicitações que você considera redirecionar. Se seu código não puder acessar um parâmetro filtrado, então esse parâmetro não poderá ser usado para o redirecionamento. Considere solicitar o componente de uma página inicial que redireciona uma solicitação de www.example.com?lang=en para o caminho específico de uma localidade como www.example.com/en. Se você filtrar o parâmetro lang, não poderá redirecionar para a localidade correta.

Considere esta sequência:

  1. O processador de solicitação trata uma solicitação dewww.example.com/?gclid=123.
  2. O processador de solicitação filtra o parâmetro da string de consulta gclid.
  3. A solicitação é encaminhada para o aplicativo com o URL completo www.example.com.
  4. O aplicativo retorna um redirecionamento para www.example.com/en.

Veja que nesta última etapa, perdemos o parâmetro original gclid, logo ele não estará disponível para o navegador depois que o usuário for redirecionado. Como solução, evite filtrar strings de consulta de solicitações que você espera redirecionar.

Agora você sabe como melhorar os acertos de cache para as solicitações de página usando uma variedade de técnicas.

Leia nosso guia Solicitações de proxy para aprender sobre cache de solicitações de API e outras vantagens de proxy.