Работа с хэшированными именами файлов из сборщика

sw-precache — это инструмент для автоматической генерации Service Worker, который кэширует ресурсы веб-приложения, обеспечивая быстрый офлайн-доступ и улучшая производительность. Одной из ключевых задач при работе с современными сборщиками, такими как Webpack или Parcel, является правильное управление хэшированными именами файлов, которые генерируются для контроля версий ресурсов.

Хэширование файлов позволяет браузеру автоматически обновлять кэш при изменении контента. Проблема заключается в том, что имена файлов не статичны, поэтому нужно корректно передавать их в sw-precache.


Настройка sw-precache для хэшированных ресурсов

Основной способ интеграции — использовать параметр staticFileGlobs, который принимает массив путей к статическим ресурсам. При работе с хэшированными файлами этот подход не всегда удобен, так как хэш в имени меняется при каждой сборке. Вместо этого используется динамическая генерация списка ресурсов через file manifest.

Пример конфигурации с использованием шаблона:

const path = require('path');
const swPrecache = require('sw-precache');
const fs = require('fs');

const buildPath = path.join(__dirname, 'dist');

function getManifestFiles() {
  const manifest = [];
  const files = fs.readdirSync(buildPath);
  files.forEach(file => {
    if (/\.(js|css|html)$/.test(file)) {
      manifest.push(`/dist/${file}`);
    }
  });
  return manifest;
}

swPrecache.write(path.join(buildPath, 'service-worker.js'), {
  staticFileGlobs: getManifestFiles(),
  stripPrefix: path.join(__dirname, 'dist'),
});

В этом примере:

  • fs.readdirSync(buildPath) считывает все файлы из папки сборки.
  • Регулярное выражение /\.(js|css|html)$/ фильтрует только нужные ресурсы.
  • stripPrefix удаляет лишний префикс пути, чтобы кэшируемые URL были корректными относительно корня сайта.

Использование sw-precache с Webpack

При интеграции с Webpack хэшированные файлы создаются с помощью [hash] или [contenthash] в имени. Для работы с ними нужно генерировать список файлов автоматически после сборки.

Пример использования в webpack.config.js:

const path = require('path');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js'
  },
  plugins: [
    new SWPrecacheWebpackPlugin({
      cacheId: 'my-app',
      filename: 'service-worker.js',
      staticFileGlobs: ['dist/**/*.{js,css,html}'],
      stripPrefix: 'dist/',
      mergeStaticsConfig: true,
      dontCacheBustUrlsMatching: /\.[0-9a-f]{8}\./
    })
  ]
};

Ключевые моменты конфигурации:

  • staticFileGlobs указывает паттерн для поиска файлов с хэшированными именами.
  • dontCacheBustUrlsMatching предотвращает добавление лишнего кэш-баста к уже хэшированным именам, так как они уникальны по содержимому.
  • stripPrefix корректирует пути для Service Worker.

Работа с динамическим кэшированием

Для файлов, чьи имена неизвестны заранее (например, генерируемые изображения или данные API), можно использовать runtimeCaching:

runtimeCaching: [
  {
    urlPattern: /\/api\//,
    handler: 'networkFirst',
    options: {
      cache: {
        name: 'api-cache',
        maxEntries: 50,
        maxAgeSeconds: 300
      }
    }
  }
]

Это позволяет Service Worker кэшировать ответы динамически, не завися от хэшированных имен, и при этом поддерживать актуальность данных.


Автоматизация с помощью манифеста

На больших проектах удобно создавать JSON-манифест с файлами сборки, а затем передавать его в sw-precache:

const buildManifest = require('./dist/asset-manifest.json');

swPrecache.write(path.join(__dirname, 'dist', 'service-worker.js'), {
  staticFileGlobs: Object.values(buildManifest),
  stripPrefix: path.join(__dirname, 'dist'),
});

Здесь:

  • asset-manifest.json формируется сборщиком и содержит все файлы с хэшами.
  • Использование манифеста исключает необходимость писать сложные регулярные выражения для фильтрации файлов.

Важные рекомендации

  • Не кэшировать Service Worker через Service Worker. Свежий service-worker.js всегда должен загружаться напрямую.
  • Всегда использовать хэши контента для файлов JS и CSS. Это исключает коллизии кэша при обновлениях.
  • Синхронизировать списки файлов с каждым билдом. Любые изменения должны автоматически отражаться в манифесте или функции генерации списка.
  • Тестировать обновления кэша в режиме инкогнито или с очисткой старого Service Worker, чтобы убедиться, что новые файлы загружаются корректно.

Эта схема работы позволяет полностью интегрировать sw-precache с любым современным сборщиком, сохраняя преимущества хэшированных файлов и минимизируя проблемы с устаревшим кэшем.