Понимание сферы обслуживания работника
Я пытаюсь реализовать Service Worker
на тестовой странице. Моя конечная цель - приложение, которое работает в автономном режиме. Структура папок ниже
/myApp
...
/static
/mod
/practice
service-worker.js
worker-directives.js
foopage.js
/templates
/practice
foopage.html
Я регистрирую работника сервиса, как показано ниже (в течение service-worker.js
):
navigator.serviceWorker.register('../static/mod/practice/service-worker.js').then(function(reg) {
console.log('Registration succeeded. Scope is ' + reg.scope);
...
}
и в консоли вижу
Registration succeeded. Scope is https://example.com/static/mod/practice/
Если моя страница находится на https://example.com/practice/foopage
мне нужно убедиться, что мой service worker
сфера https://example.com/practice/foopage
?
Если я попытаюсь определить область в register
вызов функции как
navigator.serviceWorker.register('../static/mod/practice/service-worker.js', { scope: '/practice/foopage/' }).then(function(reg) {
...
}
Я получаю ошибку
Registration failed with SecurityError: Failed to register a ServiceWorker: The path of the provided scope ('/practice/foopage/') is not under the max scope allowed ('/static/mod/practice/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
Вопрос в том, что именно означает сфера? Это коллекция URL, которые service worker
будет в итоге контролировать? Нужно ли двигаться service-workers.js
где-нибудь еще? Если так, то где?
4 ответа
Сервисные работники - это, по сути, прокси между вашим веб-приложением и Интернетом, поэтому он может перехватывать вызовы в сети, если это необходимо.
В данном случае под областью понимается путь, по которому работник службы сможет перехватывать сетевые вызовы. scope
Свойство может быть использовано в явном виде для определения области, которую оно будет охватывать. Тем не мение:
Работники службы могут перехватывать только запросы, исходящие из области текущего каталога, в котором находится сценарий работника службы, и его подкаталогов. Или, как утверждает MDN:
Сервисный работник будет получать запросы только от клиентов в рамках сервисного работника.
Максимальная область действия для работника службы - это местоположение работника.
Как ваш сервисный работник находится в /static/mod/practice/
запрещается устанавливать область действия /practice/foopage/
, Запросы к другим хостам, например https://stackru.com/foo
, может быть перехвачен в любом случае.
Самый простой способ убедиться, что ваш сервисный работник может перехватывать все необходимые вызовы, - это поместить его в корневой каталог вашего веб-приложения (/
). Вы также можете переопределить ограничения по умолчанию, используя заголовок http и вручную устанавливая область действия (см. Ответ Ашрафа Сабри).
Оставьте рабочий файл сервиса в любом каталоге, заданном структурой вашего проекта, и установите scope
возможность /
и добавить Service-Worker-Allowed
HTTP-заголовок к ответу вашего служебного рабочего файла.
Я использую IIS, поэтому я бы добавил следующее в файл web.config:
<location path="static/mod/practice/service-worker.js">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Service-Worker-Allowed" value="/" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
И зарегистрируйте работника:
navigator.serviceWorker.register('/static/mod/practice/service-worker.js', { scope: '/' })
.then(function (registration)
{
console.log('Service worker registered successfully');
}).catch(function (e)
{
console.error('Error during service worker registration:', e);
});
Проверено на Firefox и Chrome.
Обратитесь к примерам в спецификации сервисного работника.
Для людей, которые используют nginx, это не может быть проще:
# Given that /static is your route to assets
location /static {
# using / as root scope
add_header Service-Worker-Allowed /;
....
На всякий случай, если область действия меняется между средой разработки и производственной средой, как часто мы используем локальные подкаталоги для проектов, использование «./» для области действия может спасти положение (и сделать ее динамической).
navigator.serviceWorker.register(
`./service-worker.js`,
{
scope: `./`
}
);