Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

fs.watch no Node.js: monitore arquivos corretamente

Atualizado em: 30 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

fs.watch no Node.js monitora alterações em arquivos e diretórios usando os mecanismos oferecidos pelo sistema operacional. Ele é útil para recarregar configuração, observar diretórios de entrada, implementar ferramentas de desenvolvimento e iniciar pipelines após novos arquivos.

A API não é um log durável de mudanças. Eventos podem ser agrupados, duplicados ou perdidos, e o comportamento varia entre Linux, macOS e Windows. Por isso, o watcher deve servir como sinal para uma nova verificação do estado real.

Exemplo básico

import { watch } from 'node:fs';

const watcher = watch('./config', (eventType, filename) => {
  console.log({ eventType, filename });
});

watcher.on('error', error => {
  console.error('watch error', error);
});

eventType costuma ser rename ou change. O nome pode ser ausente em algumas plataformas.

Promises e iterador assíncrono

import { watch } from 'node:fs/promises';

const controller = new AbortController();

for await (const event of watch('./inbox', {
  signal: controller.signal
})) {
  console.log(event.eventType, event.filename);
}

O iterador facilita cancelamento e composição com loops assíncronos.

Eventos são pistas

Não assuma que cada evento corresponde a exatamente uma alteração. Ao receber sinal, faça stat, liste o diretório ou releia o arquivo:

async function reconcileDirectory() {
  const entries = await readdir('./inbox', { withFileTypes: true });
  return entries.filter(entry => entry.isFile());
}

Debounce

Editores frequentemente salvam por arquivo temporário e rename, gerando vários eventos. Agrupe mudanças próximas:

let timer;

function scheduleReconcile() {
  clearTimeout(timer);
  timer = setTimeout(() => {
    reconcileDirectory().catch(console.error);
  }, 100);
}

O intervalo deve equilibrar latência e quantidade de leituras.

Arquivos gravados parcialmente

Um produtor pode emitir evento enquanto ainda grava. Prefira protocolo de arquivo temporário seguido de rename atômico. O consumidor processa somente extensões finais.

Deduplicação

Registre identidade, tamanho, mtime ou checksum para evitar reprocessar o mesmo arquivo. Para efeitos externos, use idempotência durável.

Watch recursivo

O suporte a recursive varia por plataforma e versão. Teste no ambiente de produção. Em Linux, pode ser necessário criar watchers por diretório ou usar biblioteca especializada.

Limites do sistema

Muitos watchers consomem descritores e recursos do kernel. No Linux, limites do inotify podem ser atingidos. Monitore erros e evite observar árvores enormes sem necessidade.

Defina política para links simbólicos. Um diretório observado pode apontar para fora da raiz esperada. Use caminhos canônicos e verifique containment antes de processar arquivos.

Renames

Um rename pode representar criação, exclusão ou substituição. Releia o estado real:

try {
  const info = await stat(pathname);
  if (info.isFile()) await processFile(pathname);
} catch (error) {
  if (error.code !== 'ENOENT') throw error;
}

Rotação de arquivos

Logs e configurações podem ser substituídos por rename. Um watcher preso ao inode antigo pode deixar de acompanhar o novo arquivo em algumas plataformas. Observar o diretório pai costuma ser mais robusto.

Rede e volumes montados

NFS, SMB, Docker bind mounts e volumes remotos podem não entregar eventos de forma confiável. Use polling ou reconciliação periódica quando correção for importante.

fs.watchFile

fs.watchFile usa polling de estatísticas. Consome mais recursos, mas pode funcionar em ambientes onde eventos nativos são inconsistentes:

import { watchFile, unwatchFile } from 'node:fs';

watchFile('./config.json', { interval: 1000 }, (current, previous) => {
  if (current.mtimeMs !== previous.mtimeMs) reload();
});

Backpressure

Se o processamento é mais lento que a chegada de arquivos, use fila limitada. Não inicie trabalho ilimitado no callback.

Checkpoint

Para diretórios de entrada, mova arquivos processados para outra pasta ou registre status no banco. Depois de reiniciar, reconcilie todos os arquivos pendentes.

Segurança

  • não confie no nome do arquivo;
  • bloqueie path traversal;
  • verifique tamanho e tipo;
  • não siga symlinks sem política;
  • processe com permissões mínimas;
  • quarentene conteúdo não confiável.

Configuração dinâmica

Ao recarregar configuração, valide completamente antes de substituir a versão ativa:

const next = validateConfig(JSON.parse(await readFile(file, 'utf8')));
activeConfig = Object.freeze(next);

Se o arquivo estiver inválido, mantenha a configuração anterior e emita alerta.

Shutdown

process.once('SIGTERM', () => {
  watcher.close();
  clearTimeout(timer);
});

Com iterador assíncrono, aborte o controller e aguarde o loop encerrar.

Observabilidade

Monitore eventos recebidos, reconciliações, duração, fila pendente, arquivos ignorados, erros, reinícios do watcher e tempo desde o último evento.

Testes

  • criação;
  • alteração rápida;
  • rename atômico;
  • exclusão;
  • filename ausente;
  • evento duplicado;
  • arquivo parcial;
  • symlink;
  • reinício e reconciliação;
  • shutdown.

Erros comuns

  • tratar eventos como histórico completo;
  • processar imediatamente sem debounce;
  • não reler o estado;
  • concorrência ilimitada;
  • não ter reconciliação periódica;
  • ignorar diferenças de plataforma;
  • observar arquivo que é substituído por rename;
  • confiar em volumes de rede.

Conclusão

fs.watch no Node.js é adequado como mecanismo de notificação, não como fonte de verdade. O código deve transformar eventos em gatilhos para verificar novamente arquivos e diretórios.

Use debounce, idempotência, fila limitada e reconciliação. Para fluxos críticos, registre estado durável e garanta que uma reinicialização descubra tudo que ainda precisa ser processado.

Consulte a documentação oficial de fs.watch e a documentação de fsPromises.watch.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita