Как сбросить кеш require для определенной библиотеки? Как быть в случае ESM?nodejs-32

Сброс кеша для CommonJS

Основной способ через require.cache

// Удаление конкретного модуля из кеша
function clearRequireCache(modulePath) {
  delete require.cache[require.resolve(modulePath)];
}

// Пример использования
const lib = require('./lib');
clearRequireCache('./lib');
const freshLib = require('./lib'); // Будет загружена новая версия

Полный сброс зависимостей модуля

function deepClearRequireCache(modulePath) {
  const resolvedPath = require.resolve(modulePath);
  const module = require.cache[resolvedPath];

  if (module) {
    // Рекурсивно удаляем дочерние модули
    module.children.forEach(child => {
      deepClearRequireCache(child.id);
    });

    delete require.cache[resolvedPath];
  }
}

Особые случаи для CommonJS

Для JSON файлов

// JSON файлы кешируются отдельно
const data = require('./data.json');
fs.watchFile('./data.json', () => {
  delete require.cache[require.resolve('./data.json')];
  const freshData = require('./data.json');
});

Для модулей с состоянием

// Если модуль экспортирует изменяемый объект
const sharedState = require('./state-module');
sharedState.value = 'new'; // Изменения сохранятся даже после сброса кеша

Сброс кеша для ESM

Динамический импорт + параметры кеширования

let currentModule;
async function loadModule() {
  currentModule = await import('./module.mjs?' + Date.now());
}

// Принудительная перезагрузка
async function reloadModule() {
  const cacheBuster = '&cache=' + Math.random();
  currentModule = await import('./module.mjs?' + cacheBuster);
}

Использование import.meta.url

// В самом модуле можно добавить хук для перезагрузки
if (import.meta.hot) {
  import.meta.hot.accept(() => {
    console.log('Module was updated');
  });
}

Полноценный HMR

Для ESM потребуются дополнительные инструменты:

  1. Vite
  2. Webpack с ESM поддержкой
  3. Специальные загрузчики модулей

Различия в поведении CommonJS и ESM

Аспект CommonJS (require) ESM (import)
КешированиеЯвное через require.cacheНет прямого доступа к кешу
ПерезагрузкаПростая через delete cacheТребует обходных путей
Состояние модуляСохраняется в кешеИзолировано при перезагрузке
Динамическая загрузкаrequire() синхронныйimport() асинхронный

Лучшие практики

  1. Для разработки:

    • Используйте nodemon для автоматической перезагрузки
    • Для ESM рассмотрите Vite или аналоги
  2. Для продакшена:

    • Избегайте частого сброса кеша
    • Реализуйте graceful reload через кластер/воркеры
  3. Для конфигураций:

    // Вместо require лучше читать файл напрямую
    const getConfig = () => JSON.parse(fs.readFileSync('./config.json'));
    

Резюмируем

  1. CommonJS:

    • Используйте delete require.cache[require.resolve(modulePath)]
    • Для глубокого сброса очищайте дочерние модули
    • Особо следите за модулями с состоянием
  2. ESM:

    • Нет прямого доступа к кешу
    • Используйте параметры запроса для обхода кеша (?timestamp)
    • Рассмотрите HMR решения для горячей перезагрузки
  3. Общие рекомендации:

    • В разработке используйте инструменты вроде nodemon
    • В продакшене минимизируйте перезагрузки
    • Для конфигов предпочитайте прямое чтение файлов