Neste codelab, mostramos como mudar os cabeçalhos de armazenamento em cache HTTP retornados por um servidor da Web baseado em Node.js, executando o framework de exibição Express. Ele também mostra como confirmar se o comportamento de armazenamento em cache esperado está sendo aplicado usando o painel Network no DevTools do Chrome.
Conhecer o projeto de exemplo
Estes são os principais arquivos com que você vai trabalhar no projeto de exemplo:
server.jscontém o código Node.js que exibe o conteúdo do app da Web. Ele usa o Express para processar solicitações HTTP e respostas. Em particular,express.static()é usado para exibir todos os arquivos locais no diretório público, então a documentação doserve-staticserá útil.public/index.htmlé o HTML do app da Web. Como a maioria dos arquivos HTML, ele não contém informações de controle de versões como parte do URL.public/app.15261a07.jsepublic/style.391484cf.csssão os recursos de JavaScript e CSS do app da Web. Cada um desses arquivos contém um hash no URL, correspondente ao conteúdo. Oindex.htmlé responsável por acompanhar qual URL com controle de versão específico deve ser carregado.
Configurar cabeçalhos de armazenamento em cache para nosso HTML
Ao responder a solicitações de URLs que não contêm informações de controle de versões, adicione Cache-Control: no-cache às mensagens de resposta. Além disso, é recomendável definir um dos dois cabeçalhos de resposta adicionais:
Last-Modified
ou ETag. O
index.html se enquadra nessa categoria. É possível dividir isso em duas etapas.
Primeiro, os cabeçalhos Last-Modified e ETag são controlados pelas opções de configuração etag e lastModified. Ambas as opções usam true como padrão para todas as respostas HTTP. Portanto, nessa configuração atual, você não precisa ativar esse comportamento. Mas você pode ser explícito na configuração de qualquer maneira.
Em segundo lugar, você precisa adicionar o cabeçalho Cache-Control: no-cache, mas
apenas para seus documentos HTML (index.html, neste caso). A maneira mais fácil de
definir esse cabeçalho condicionalmente é escrever um
setHeaders function
personalizado e, nele, verificar se a solicitação recebida é para um documento HTML.
A configuração de veiculação estática em server.js começa assim:
app.use(express.static('public'));
- Faça as mudanças descritas acima para que o resultado seja parecido com este:
app.use(express.static('public', {
etag: true, // Just being explicit about the default.
lastModified: true, // Just being explicit about the default.
setHeaders: (res, path) => {
if (path.endsWith('.html')) {
// All of the project's HTML files end in .html
res.setHeader('Cache-Control', 'no-cache');
}
},
}));
Configurar cabeçalhos de armazenamento em cache para os URLs com controle de versão
Ao responder a solicitações de URLs que contêm
"impressão digital" ou
informações de controle de versões e cujo conteúdo nunca deve mudar, adicione
Cache-Control: max-age=31536000 às suas respostas. app.15261a07.js e
style.391484cf.css se enquadram nessa categoria.
Com base no
setHeaders function
usado na última etapa, é possível adicionar mais lógica para verificar se uma determinada
solicitação é para um URL com controle de versão e, em caso afirmativo, adicionar o cabeçalho Cache-Control:
max-age=31536000.
A maneira mais robusta de fazer isso é usar uma
expressão regular
para conferir se o recurso solicitado corresponde a um padrão específico que você
sabe que os hashes seguem. No caso deste projeto de exemplo, são sempre oito
caracteres do conjunto de dígitos de 0 a 9 e as letras minúsculas de a a f (ou seja,
caracteres hexadecimais). O hash
é sempre separado por um caractere . em ambos os lados.
Uma expressão regular que
corresponde a essas regras gerais
pode ser expressa como new RegExp('\\.[0-9a-f]{8}\\.').
- Modifique a função
setHeaderspara que ela fique assim:
app.use(express.static('public', {
etag: true, // Just being explicit about the default.
lastModified: true, // Just being explicit about the default.
setHeaders: (res, path) => {
const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');
if (path.endsWith('.html')) {
// All of the project's HTML files end in .html
res.setHeader('Cache-Control', 'no-cache');
} else if (hashRegExp.test(path)) {
// If the RegExp matched, then we have a versioned URL.
res.setHeader('Cache-Control', 'max-age=31536000');
}
},
}));
Confirmar o novo comportamento usando o DevTools
Com as modificações no servidor de arquivos estáticos, você pode verificar se os cabeçalhos certos estão sendo definidos. Para isso, visualize o app em tempo real com o painel Network do DevTools aberto.
- Personalize as colunas exibidas no painel Network para incluir as informações mais relevantes. Para isso, clique com o botão direito do mouse no cabeçalho da coluna:

Aqui, as colunas que merecem atenção são Name, Status, Cache-Control,
ETag e Last-Modified.
- Com o DevTools aberto no painel Network, atualize a página.
Depois que a página for carregada, você verá entradas no painel Network semelhantes a estas:

A primeira linha é para o documento HTML que você acessou. Isso é veiculado
corretamente com Cache-Control: no-cache. O status de resposta HTTP para essa solicitação
é um 304. Isso
significa que o navegador sabia que não deveria usar o HTML armazenado em cache imediatamente, mas
fez uma solicitação HTTP ao servidor da Web, usando as informações Last-Modified e ETag
para conferir se havia alguma atualização no HTML que já estava no
cache. A resposta HTTP 304 indica que não há HTML atualizado.
As duas linhas seguintes são para os recursos de JavaScript e CSS com controle de versão. Você vai
ver que eles são exibidos com Cache-Control: max-age=31536000, e o status HTTP de
cada um é 200.
Devido à configuração usada, nenhuma solicitação real está sendo feita ao
servidor Node.js. Ao clicar na entrada, você verá mais detalhes,
incluindo que a resposta veio "(do cache em disco)".

Os valores reais das colunas ETag e Last-Modified não importam muito. O importante é confirmar se eles estão sendo definidos.
Resumindo
Depois de seguir as etapas deste codelab, você já sabe como configurar os cabeçalhos de resposta HTTP em um servidor da Web baseado em Node.js usando o Express para otimizar o uso do cache HTTP. Você também tem as etapas necessárias para confirmar que o comportamento de armazenamento em cache esperado está sendo usado, por meio do painel Network no DevTools do Chrome.