#javascript #service-worker #progressive-web-apps #fetch-api
#javascript #service-worker #progressive-web-apps #fetch-api
Вопрос:
У меня есть PWA, в котором есть a manifest.json
с a start_url
.
У меня есть service worker с fetch
событием, которое кэширует только определенные запросы. Это делается в service worker путем переопределения ответа на прокси из кэша (машинопись для ясности):
self.addEventListener('fetch', (event: FetchEvent) => {
// This MUST be synchronous until respondWith is called
const cache = isCachable(event.request);
if (!isCachable)
return; // Don't proxy, let the network request continue
// Kick off a promise to check the cache, and clone/cache the response otherwise
const proxy: Promise<Response> = cacheResponse(event);
event.respondWith(proxy);
}
Я хочу кэшировать start_url
, что означает isCachable
, что выше должно быть указано, что значение start_url
является запрашиваемым относительным маршрутом.
Я могу загрузить manifest.json
в SW, но это кажется действительно неуклюжим. Я могу жестко запрограммировать значения в SW, но затем мне нужно обновить два места, если конфигурация изменится.
В fetch
обработчике event.request.url
является абсолютным, но start_url
относительным к manifest.json
— так, например, я мог бы иметь:
manifest.json
:{ "start_url": "appshell" ... }
- Веб-сайт развертывается на
www.example.com/folder/
(но может быть развернут наsub.example.com
илиwww.example.com/a/b
или что-то еще) - Онлайн-пользователь посещает сайт, либо посещает все, либо устанавливает кэш скрипта напрямую.
- Позже тот же пользователь переходит в автономный режим.
- Приведенная выше выборка срабатывает с
event.request.url === 'www.example.com/folder/appshell'
- Мне нужно
isCachable
, чтобы функция могла указывать, что ресурс должен кэшироваться синхронно. Ему необходимо определить, чтоwww.example.com/folder/appshell
этоappshell
(разрешить относительную ссылку), и этоappshell
установлено какstart_url
(прочитать манифест).
Очевидно, что все это может быть жестко запрограммировано. Однако для каждого PWA требуется ответ из кэша start_url
, поэтому это не может быть новой проблемой. Прежде чем я изобрету колесо, есть ли лучший способ или что-то, чего мне не хватает?
Итак…
- Учитывая, что работникам службы нужен манифест, есть ли хороший способ получить конфигурацию манифеста в воркере?
- Есть ли способ разрешить относительную ссылку для сравнения с манифестом?
Комментарии:
1. Вы говорите о манифесте веб-приложения, верно? Не о расширении?
2. И ваш вопрос касается только разрешения относительных путей? Если да, вы хотите разрешить его относительно SW или из документа, который отправил запрос?
3. @Kaiido есть только один
manifest.json
, который применяется к работникам службы. Да, это прогрессивное веб-приложение, а не расширение для браузера.start_url
Относится к манифесту.event.request.url
Переданныйfetch
обработчику в service worker является абсолютным, кэш в service worker относится к service worker. Мне не нужно искать относительные ссылки где-либо еще, этот вопрос касается только конкретного случая начального URL-адреса, который должен быть кэширован service worker.4. Тогда почему вы продолжаете использовать тег, предназначенный для веб-расширений? И отредактированная вами ссылка на документацию устарела, с тех пор появилось новое расширение. webmanifest был официально оформлен.
5. @Kaiido потому что это конкретно вопрос о manifest.json , а контекст service worker гораздо более понятен, чем контекст расширения (угадайте, какой из них является лучшим в поиске?), И оба являются вариантами одного и того же.
Ответ №1:
Я понял, как это сделать, но это неприятно, и я уверен, что есть лучший способ.
В частности, я жестко программирую встроенный манифест (я мог fetch
бы это сделать, но это тоже неприятно).
const manifest = { start_url: 'appshell' };
Затем я использую self.location
, чтобы получить путь к service worker. Это включает в себя имя файла, поэтому я обрезаю его в конце:
// if file is 'sw.js' that's 5 chars off the end
const applicationRoot = new URL(self.location.href.slice(0, -5) manifest.start_url);
Тогда я могу проверить это:
self.addEventListener('fetch', (event: FetchEvent) => {
// This MUST be synchronous until respondWith is called
const url = new URL(event.request.url);
if (url.pathname === applicationRoot.pathname) {
// Request is for the start_url, always return something so the PWA starts offline
event.respondWith(...):
}
// ... see question for rest
});
Это неуклюже, но, по крайней мере, он всегда может обслуживать кэш start_url
, не кэшируя все остальное, так что на данный момент это принятый ответ. Мне бы хотелось увидеть лучший способ сделать это, в идеале без жесткого кодирования / выборки manifest.json
, чтобы изменения конфигурации там не требовали нового service worker.