Понимание сферы обслуживания работника

Я пытаюсь реализовать 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: `./`
    }
);
Другие вопросы по тегам