Современная альтернатива importScripts().
Фон
Модули ES уже давно стали фаворитом разработчиков. В дополнение к ряду других преимуществ , они обещают универсальный формат модуля, в котором общий код может быть выпущен один раз и запускаться в браузерах и в альтернативных средах выполнения, таких как Node.js. Хотя все современные браузеры предлагают некоторую поддержку модулей ES, не все они предлагают поддержку везде, где может быть запущен код. В частности, поддержка импорта ES-модулей внутри сервис-воркера браузера только начинает становиться более доступной.
В этой статье подробно описано текущее состояние поддержки модулей ES в сервис-воркерах в распространенных браузерах, а также некоторые ошибки, которых следует избегать, а также рекомендации по доставке обратно совместимого кода сервис-воркеров.
Варианты использования
Идеальный вариант использования модулей ES внутри сервисных работников — это загрузка современной библиотеки или кода конфигурации, совместно используемого с другими средами выполнения, поддерживающими модули ES.
Попытка поделиться кодом таким образом до модулей ES повлекла за собой использование старых «универсальных» форматов модулей, таких как UMD , которые включали ненужный шаблон, и написание кода, который вносил изменения в глобально открытые переменные.
Скрипты, импортированные через модули ES, могут инициировать поток обновления Service Worker, если их содержимое изменится, что соответствует поведению importScripts()
.
Текущие ограничения
Только статический импорт
Модули ES можно импортировать одним из двух способов: либо статически , используя синтаксис import ... from '...'
, либо динамически , используя метод import()
. Внутри сервис-воркера в настоящее время поддерживается только статический синтаксис.
Это ограничение аналогично аналогичному ограничению, налагаемому на использование importScripts()
. Динамические вызовы importScripts()
не работают внутри сервис-воркера, и все вызовы importScripts()
, которые по своей сути являются синхронными, должны завершиться до того, как сервис-воркер завершит этап install
. Это ограничение гарантирует, что браузер знает и может неявно кэшировать весь код JavaScript, необходимый для реализации сервис-воркера во время установки.
Со временем это ограничение может быть снято и будет разрешен динамический импорт модулей ES. На данный момент убедитесь, что вы используете статический синтаксис только внутри сервис-воркера.
А как насчет других работников?
Поддержка модулей ES в «выделенных» рабочих процессах — тех, которые созданы с помощью new Worker('...', {type: 'module'})
- более широко распространена и поддерживается в Chrome и Edge, начиная с версии 80 , а также последние версии Safari. В выделенных рабочих процессах поддерживается как статический, так и динамический импорт модулей ES.
Chrome и Edge поддерживают модули ES в общих рабочих процессах начиная с версии 83 , но на данный момент ни один другой браузер не поддерживает эту поддержку.
Нет поддержки импорта карт.
Карты импорта позволяют средам выполнения перезаписывать спецификаторы модулей, например, добавляя URL-адрес предпочтительного CDN, из которого можно загружать модули ES.
Хотя Chrome и Edge версии 89 и выше поддерживают карты импорта, в настоящее время их нельзя использовать с работниками службы.
Поддержка браузера
Модули ES в сервис-воркерах поддерживаются в Chrome и Edge, начиная с версии 91 .
Safari добавил поддержку в Technology Preview 122 Release , и разработчикам следует ожидать появления этой функции в стабильной версии Safari в будущем.
Пример кода
Это базовый пример использования общего модуля ES в контексте window
веб-приложения с одновременной регистрацией сервисного работника, который использует тот же модуль ES:
// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
import {cacheName} from './config.js';
// Do something with cacheName.
await navigator.serviceWorker.register('es-module-sw.js', {
type: 'module',
});
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(cacheName);
// ...
})());
});
Обратная совместимость
Приведенный выше пример работал бы нормально, если бы все браузеры поддерживали ES-модули в сервис-воркерах, но на момент написания этой статьи это не так.
Чтобы обеспечить поддержку браузеров, не имеющих встроенной поддержки, вы можете запустить сценарий сервисного работника через пакетный модуль, совместимый с модулем ES, чтобы создать сервисный работник, который включает в себя весь код модуля и будет работать в старых браузерах. Альтернативно, если модули, которые вы пытаетесь импортировать, уже доступны в форматах IIFE или UMD , вы можете импортировать их с помощью importScripts()
.
Как только у вас появятся две версии вашего сервис-воркера — одна использует модули ES, а другая — нет, вам нужно будет определить, что поддерживает текущий браузер, и зарегистрировать соответствующий скрипт сервис-воркера. Рекомендации по обнаружению поддержки в настоящее время постоянно меняются, но вы можете следить за обсуждением в этом выпуске GitHub, чтобы получить рекомендации.
_Фото Владо Пауновича на Unsplash _