Работа с веб-воркерами в Webpack 5, как быть со scope при регистрации сервис-воркера?



В пятом вебпаке появилась нативная поддержка веб-воркеров. Раньше для работы с ними нужно было использовать сторонние плагины (например workbox-webpack-plugin), а теперь ничего допонительно устанавливать не нужно. На примеры работы с воркерами можно взглянуть в примерах использования в репозитории вебпака.



Но при работе с сервис-воркерами возникает один важный нюанс.



Сервис-воркер по умолчанию может перехватывать запросы совпадающие с путем до файла с воркером. Т.е. сервис-воркер расположенный в domain.com/static/service-worker.js сможет работать с запросами domain.com/static/**, а вот domain.com/some-path перехватить уже не выйдет. При регистрации сервис-воркеру можно передать опцию scope, однако таким способом можно только сузить допустимые URL, а расширить не выйдет — будет ошибка при регистрации. Это важно, т.к. часто ассеты как раз таки раздают из какой-нибудь отдельной директории, например static, т.к. таким образом проще управлять кешом и другими заголовками.



У этой проблемы есть два решения.



1. HTTP заголовок service-worker-allowed

С помощью этого заголовка можно расширить скоуп. Это более чем валидный способ, но для этого надо лезть в настройки сервера, который отвечает за ассеты на проде (условный nginx) и добавлять заголовки для дев-сервера. А в идеале применять этот заголовок только к ассету с сервис-воркером, что ведет к усложению конфигурации.



2. «Магический» комментарий webpackEntryOptions

Magic comments, кажется, появились ещё во втором вебпаке. Они нужны, чтобы конфигурировать асинхронные импорты. Например, через них можно задать название для чанка. С воркерами эти комментарии тоже работают, но нас интересует другой комментарий — webpackEntryOptions (он, кстати, не задокументирован). Через этот комментарий можно указать любые опции, доступные для энтри-поинта (это advanced API, мало кто знает, что в качестве точки входа можно передать объект). Таким образом для всех ассетов в конфиге можно указать output.filename: “static/[name].js”, а при регистрации воркера добавить комментарий /* webpackEntryOptions: { filename: "[name].js" } */. И тогда не придётся проставлять никакие заголовки и проблема со скоупом отпадёт сама собой.



А начиная с 5.33 версии для энтри-поинта так же можно указывать и кастомный publicPath.