Menu

express.static: servir arquivos estáticos no Express

app.use(express.static(path.join(__dirname, 'public'))) serve todos os arquivos da pasta public na URL correspondente: public/style.css responde /style.css. Adicione um caminho de montagem para servi-los com um prefixo.

Esta página tem editores executáveis. Edite, execute e veja a saída na hora.

express.static é o middleware nativo que serve arquivos de uma pasta. app.use(express.static(path.join(__dirname, 'public'))) deixa cada arquivo de public disponível no mesmo caminho da URL: public/style.css responde /style.css, e public/index.html responde /. O Express define o Content-Type pela extensão do arquivo e, quando nenhum arquivo corresponde, passa a requisição para as suas rotas em vez de responder 404.

A resposta para GET /style.css é o texto do arquivo, com Content-Type: text/css; charset=utf-8 na aba Headers. Envie GET / para receber o index.html, depois GET /api/time: esse arquivo não existe, então a rota responde.

Por que o caminho da pasta precisa de __dirname

express.static('public') resolve 'public' a partir da pasta de onde você iniciou o Node, não da pasta em que está o server.js. Funciona quando você roda node server.js dentro do projeto e quebra quando um gerenciador de processos ou um script inicia o app de outro lugar:

// project/server.js uses express.static('public')
// cd project && node server.js      -> serves project/public
// node project/server.js            -> looks for ./public, every file is 404

path.join(__dirname, 'public') é a pasta ao lado do arquivo que contém a linha, não importa de onde o Node foi iniciado. Em um ES module, use path.join(import.meta.dirname, 'public') (Node 20.11 em diante). A página do módulo path cobre __dirname e path.join em detalhe.

Servir arquivos com um prefixo

Passe um caminho de montagem primeiro para servir a pasta sob um prefixo de URL. O prefixo não faz parte do caminho do arquivo no disco:

GET /assets/app.js retorna console.log("hi"); como text/javascript, e GET /assets/img/dot.svg chega na subpasta. Envie GET /app.js sem o prefixo: dá 404, porque os arquivos só existem sob /assets. Use um prefixo para que as URLs dos arquivos não colidam com as rotas da sua API.

Headers de cache com maxAge

Por padrão o Express envia Cache-Control: public, max-age=0, então os navegadores confirmam com o servidor a cada uso (e recebem um 304 Not Modified rápido quando o arquivo não mudou, graças ao header ETag). Para arquivos cujo nome muda a cada build, como app.3f9a1c.js, diga aos navegadores para guardá-los:

Abra a aba Headers: Cache-Control agora é public, max-age=604800, sete dias em segundos. index: false desliga o envio do index.html para URLs de pastas. Outras opções úteis são extensions: ['html'], que faz /about encontrar about.html, e dotfiles, que é 'ignore' por padrão para que arquivos como .env nunca sejam servidos.

Single page apps: voltar para o index.html

Um app React ou Vue feito com roteamento no cliente precisa que todo caminho desconhecido retorne o index.html, para que um reload em /settings não dê 404. Coloque o fallback depois do express.static e das rotas da API:

app.use(express.static(path.join(__dirname, 'dist')));
app.use('/api', apiRouter);

// Express 5 wildcard syntax
app.get('/*splat', (req, res) => {
    res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});

Erros comuns

Incluir o nome da pasta na URL. Com app.use(express.static('public')) a URL é /style.css, não /public/style.css. Se você quer /public na URL, monte assim: app.use('/public', express.static(...)).

Linkar arquivos com caminhos relativos no HTML. <link href="style.css"> na página /blog/post pede /blog/style.css. Comece o caminho com barra: /style.css.

Colocar segredos na pasta estática. Tudo o que está nela é público. Deixe arquivos de config, chaves e código-fonte fora dela.

Perguntas frequentes

Posso usar express.static mais de uma vez?

Sim. Registre um por pasta; o Express procura nelas na ordem em que você as adicionou e serve o primeiro arquivo que encontrar. Dê a cada um o seu próprio caminho de montagem quando as pastas puderem ter arquivos com o mesmo nome.

O Express deve servir arquivos estáticos em produção?

Para apps pequenos, tudo bem. Com muito tráfego, coloque uma CDN ou um reverse proxy como o Nginx na frente, que serve arquivos mais rápido e faz cache mais perto dos usuários, e deixe o Express para a API.

Como envio um arquivo específico a partir de uma rota?

Use res.sendFile(path.join(__dirname, 'files', 'report.pdf')). O caminho precisa ser absoluto (ou você passa a opção root). Use res.download() quando o navegador deve salvar o arquivo em vez de exibi-lo.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

Começar