Не уверен, насколько хорошо вы разбираетесь в сервис-воркерах, но если вы писали сервис-воркер в прошлом, вы, вероятно, написали бы его в виде одного файла или имели бы несколько файлов, но должны были использовать ключевое слово importScripts для синхронной загрузки файлов. Но если бы вы были на моем месте, вы, вероятно, подумали бы, могу ли я использовать структуру import и export, как в модулях ES? Изначально нельзя, но с парой изменений точно можно. Эта статья посвящена тому, как помочь вам использовать webpack для написания модульного сервис-воркера.

В чем проблема?

Когда я начал работать над проектом PWA на работе, моей задачей было использовать Service Worker для повышения производительности приложения и предоставления богатой экосистемы собственных функций приложения, таких как push-уведомления, фоновая синхронизация и автономные возможности.

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

Я хотел использовать модульную структуру модулей ES для сервис-воркера, но мне не удалось найти в Интернете какие-либо ресурсы о том, как упаковать модули сервис-воркера в один файл, который понадобится основному приложению после его загрузки на клиенте. .

Решения, которые я пробовал

Пропустите этот раздел, если вы спешите🏃.

  1. Попытался добавить работника службы в качестве записи в конфигурации веб-пакета.
  2. Пытался написать плагин webpack, который будет использовать хуки компилятора, получать доступ к объекту компиляции и запускать дочерний компилятор, который может скомпилировать файлы сервис-воркеров в отдельный бандл.
  3. Пытался написать загрузчик webpack, который будет загружать файлы сервис-воркера в отдельный бандл.

К сожалению, ни один из них не работал для меня.

Добавление его в качестве точки входа не сработало, потому что веб-пакет создавал общие фрагменты, которые, как он предполагает, понадобятся и клиенту, и работнику службы, и могут ими поделиться. Но когда сервис-воркер загружался, клиент загружал общий фрагмент, содержащий вещи, которые среда сервис-воркера не понимает, например объект window. Кроме того, документация веб-пакета не рекомендует вам добавлять точку входа, которая не обслуживает определенную страницу (сервисный работник обслуживает приложение, а не страницу).

Это решение подойдет для простых сервисных работников, но сложные, например те, которые могут понадобиться приложению PWA, не запустятся. Другим примером могут быть общие служебные модули, такие как lodash, которые могут использовать клиент и сервисный работник.

Написание плагина и загрузчика веб-пакета не удалось по тем же причинам. Создание дочернего компилятора было очень сложно понять, поскольку он не задокументирован как часть документации веб-пакета. Кроме того, объект компилятора будет использовать ту же конфигурацию, которая может быть проблемой, если вы хотите использовать другую конфигурацию для приложения и работника службы. Кроме того, даже если мы сможем найти способ создать дочерний компилятор, они будут работать синхронно, увеличивая время сборки.

Каково решение?

Решение довольно простое. Создайте другой дочерний процесс компиляции веб-пакета для работника службы, предоставив массив конфигураций вместо одной конфигурации для веб-пакета, 1 для клиента и другой для работника службы.

Предоставляя 2 конфига, wepack будет строить их независимо, не делясь какими-либо чанками или модулями. Это также распараллеливает их, ускоряя процесс сборки, даже несмотря на то, что мы добавляем совершенно новую компиляцию.

Почему мне нравится это решение?

  1. Это решение лучше, чем использование собственного importScripts, потому что importScripts использует синхронную загрузку файлов, загружая их с сервера. Каждый новый запрос к серверу создает дополнительную нагрузку для браузера (если только вы не используете HTTP2).
  2. Это решение позволяет вам писать код на ES6 или более поздних версиях и использовать babel-loader для преобразования их в то, что понимает браузер (теперь, когда у нас есть отдельная конфигурация для сервис-воркера).
  3. Он не увеличивает время сборки из-за параллельного выполнения, хотя это новая компиляция в дополнение к существующему процессу компиляции.
  4. Кроме того, он более масштабируем, поскольку его можно использовать для других воркеров, а не только для сервис-воркеров, поскольку сервис-воркер — это особый тип веб-воркеров.

Вывод

Надеюсь, все это имело смысл.

Service Worker — отличное дополнение к веб-разработке. Это как бесконечная NOS для вашего приложения. Используйте его в полной мере, и теперь, благодаря этой статье, вы знаете, как поддерживать и масштабировать его в будущем.