Кеширование файлов с помощью Webpack + Service Worker

Я работаю над проектом, который состоит из множества репозиториев. Один из них содержит JS-код приложения, другой - серверную часть, на которой хранится index.html.

У нас есть требование, чтобы наше приложение было доступно для работы в автономном режиме. Это было сделано уже с помощью функции appcache. Но в какой-то момент мы решили пойти дальше и использовать для этой функции Service Worker (SW).

Итак, моя история о том, как я добавил генерацию SW с помощью Webpack и решал проблемы (например, кеширование запросов cors, когда сервер не разрешает cors и т. Д.)

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

Также обратите внимание, что ПО включено только через https. Если вы пишете и тестируете его на локальном сервере, хранящемся через http, вы можете сделать это (в FireFox): перейдите в

about: config

набор

devtools.serviceWorkers.testing.enabled = true

Теперь ПО будет работать с открытыми инструментами разработчика в FF.

Итак, откройте index.html и добавьте код, который будет регистрировать SW:

if ('serviceWorker' в навигаторе) {

navigator.serviceWorker.register (‘/ sw.js’)

.catch ((e) = ›{

выдать новую ошибку («Ошибка при регистрации сервис-воркера:» + e.message);

});

}

Следующий шаг - добавить генерацию ПО в конфигурацию webpack:

// импортировать плагины.

// WriteFilePlugin необходим для разрешения файловых файлов webpack в файловую систему.

// WorkboxPlugin содержит плагин, который будет генерировать ПО

const WriteFilePlugin = require («напишите-файл-webpack-плагин»);

const WorkboxPlugin = require (‘workbox-webpack-plugin’);

Самый общий код плагина генератора ПО:

function serviceWorkerConfig () {

возвращение {

плагины: [

новый WorkboxPlugin.GenerateSW ({

swDest: path.resolve (DIST_PATH, ‘/service-worker/sw.js’),

importsDirectory: path.resolve (DIST_PATH, ‘/ service-worker /’)

}),

новый WriteFilePlugin ()

]

};

}

swDest - установить путь к файлу sw.js

importsDirectory - укажите путь к файлу манифеста для предварительного кеширования (он создается автоматически)

Теперь мы можем добавить код, который заставляет SW кэшировать файлы или запросы:

новый WorkboxPlugin.GenerateSW ({

runtimeCaching: [

{

urlPattern: ‘/ offline-app? Forcew’,

обработчик: «networkFirst»,

опции: {

fetchOptions: {

режим: ‘no-cors’,

},

},

};

],

Это заставит SW обрабатывать все запросы ‘/ offline-app? Forcew’. ВНИМАНИЕ: ПО будет обрабатывать только запросы «/ offline-app? Forcew», но не запросы «/ offline-app». ПО чувствительно к параметрам запроса.

обработчик - описывает, какую стратегию использовать. «NetworkFirst» означает, что ПО всегда будет запрашивать ресурс и только при потере соединения будет принимать кэшированное значение.

fetchOptions.mode: «no-cors» означает, что ресурсы находятся в том же домене, что и SW.

Также мы можем кешировать запросы для некоторых api. И установите максимальный возраст кеша.

runtimeCaching: [

{

urlPattern: ‘https://someApi.example.com/….’,

обработчик: «cacheFirst»,

опции: {

fetchOptions: {

режим: «корс»,

},

cacheName: ‘cache-with-expiration’,

// в секундах

срок действия: 24 * 60 * 60,

},

Здесь мы использовали fetchOptions.mode: «cors», что означает, что ресурсы размещаются в другом домене, который разрешает запросы cors.

Также мы использовали параметр cacheName, который позволит SW хранить кеш в отдельной структуре и аннулировать его по истечении времени, установленного в параметре истечения срока.

Также я столкнулся с проблемой, когда мы не могли изменить настройки сервера, на котором хранятся изображения, чтобы разрешить запросы cors. Но выход есть:

runtimeCaching: [

{

urlPattern: ‘https://someServer.example.com/….’,

обработчик: «cacheFirst»,

опции: {

fetchOptions: {

режим: ‘no-cors’,

},

cacheableResponse: {статусы: [0, 200]}

},

Когда ПО делает запрос к серверу, который не поддерживает cors, ответ имеет статус 0. Это непрозрачный ответ. И ПО не может их кэшировать. Но если вы уверены, что ответ будет правильным и не вернет 500 или иначе, вы можете принудительно кэшировать его, используя fetchOptions.mode: ‘no-cors’ и cacheableResponse: {statuses: [0, 200]}.

И последнее: когда вы развертываете новую версию ПО и хотите принудительно активировать ПО, как только пользователь перезагружает страницу, вы можете использовать skipWaiting: true:

плагины: [

новый WorkboxPlugin.GenerateSW ({

swDest: path.resolve (DIST_PATH, ‘/service-worker/sw.js’),

importsDirectory: path.resolve (DIST_PATH, ‘/ service-worker /’),

skipWaiting: правда,

runtimeCaching: […]

}

Это все.