Как преобразовать манифест кэша приложения в работника службы - PullRequest
1 голос
/ 11 марта 2020

Кэш приложения устарел , а браузеры типа Chrome убирают поддержку .

У нас есть приложение, которое может работать на 100% в автономном режиме при хранении данных. в indexeddb и синхронизации позже, когда пользователь снова в сети. Нам нужно перевести этот сайт с использования кэша приложения на сервисного работника . Мы будем использовать Workbox для нашего сервисного работника.

Существует три основных раздела нашего манифеста кэша, которые мы должны скрыть.

CACHE Section Это список активов для предварительного кэширования. Это, пожалуй, самый прямой переход, так как мы используем рабочий ящик для предварительного кэширования этих файлов .

NETWORK Section Мы используем * здесь (вероятно, наиболее распространенный), поэтому это, вероятно, не будет проблемой.

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

Пример:

FALLBACK:
/search /login
/customer-edit /login
/foo-bar-baz /login
...

Мой вопрос:

Есть ли либо 1) общее руководство по преобразованию кэша приложения / манифеста кэша для работников службы, либо 2) некое конкретное c руководство по преобразованию раздела FALLBACK в эквивалентные функции в работнике службы.

Google и Утка Утка Go не была чрезвычайно полезна.

Существуют проекты по обновлению кэша приложений для работников сферы обслуживания, но большинство из них выглядят очень бета, например, из Google Chrome Лаборатории: github.com/GoogleChromeLabs/sw-appcache-behavior

1 Ответ

1 голос
/ 31 марта 2020

Это решение, которое я придумала, используя рабочий ящик Google .

Sidenote: Workbox, похоже, имеет решение для наиболее распространенных сценариев использования служащим и имеет очень гибкий дистрибутив модель, с которой довольно легко работать, либо в ванильной среде js, либо с выбранной вами структурой.

В итоге мы преобразовали наш серверный AppCache (код кэшированного манифеста) для создания работника сервиса. ( Как предварительно кэшировать список URL-адресов из файла json? )

В зависимости от языка на стороне сервера ваш код будет отличаться, но это конечный продукт, который работал для us:

service-worker. js (сгенерированный сервер)


    const productVersion = "3.01";

    importScripts('/assets/workbox/workbox-sw.js');

    workbox.setConfig({
        modulePathPrefix: '/assets/workbox/'
    });

    const { precacheAndRoute, createHandlerBoundToURL } = workbox.precaching;
    const { NavigationRoute, registerRoute, setCatchHandler } = workbox.routing;

    precacheAndRoute([
        // cache index html
        {url: '/', revision: '3.01' },

        // web workers
        {url: '/assets/some-worker.js?ver=3.01', revision: '' },
        {url: '/assets/other-worker.js?ver=3.01', revision: '' },
        // other js files
        {url: '/assets/shared-function.js', revision: '3.01' },
        // ... removed for brevity
        // css
        {url: '/assets/site.css', revision: '3.01' },
        {url: '/assets/fonts/fonts.css', revision: '3.01' },
        // svg's
        {url: '/assets/images/icon.svg', revision: '3.01' },
        {url: '/assets/images/icon-2.svg', revision: '3.01' },

        // png's
        {url: '/assets/images/img-1.png', revision: '3.01' },
        {url: '/assets/images/favicon/apple-touch-icon-114x114.png', revision: '3.01' },
        // ...
        // ...

        // fonts
        {url: '/assets/fonts/lato-bla-webfont.eot', revision: '3.01' },
        {url: '/assets/fonts/lato-bla-webfont.ttf', revision: '3.01' },

        // sounds
        {url: '/assets/sounds/keypress.ogg', revision: '3.01' },
        {url: '/assets/sounds/sale.ogg', revision: '3.01' },
    ]);

    // Routing for SPA
    // This assumes DEFAULT_URL has been precached.
    const DEFAULT_URL = '/';
    const handler = createHandlerBoundToURL(DEFAULT_URL);
    const navigationRoute = new NavigationRoute(handler, {
        denylist: [
            new RegExp('/ping'),
            new RegExp('/upgrade'),
            new RegExp('/cache.manifest'),
      ],
    });
    registerRoute(navigationRoute);

    // This allows the main window to signal the service worker that
    // it should go ahead and install if it's waiting.
    addEventListener('message', (event) => {
        if (event.data && event.data.type === 'SKIP_WAITING') {
            skipWaiting();
        }
    });


  1. Есть еще несколько вещей, на которые стоит обратить внимание. Нам пришлось выяснить, как плавно перейти с App? Cache на Service Workers. Оказывается, генерация пустого кеш-манифеста для нас сделала свое дело.
  2. У нас уже был процесс обновления (запрос пользователя на обновление или принудительное автоматическое обновление c с таймером обратного отсчета), поэтому нам пришлось проделать некоторую работу, чтобы заставить его работать с сервисными работниками. Обратите внимание, что конец файла рабочего сервиса имеет код addEventListener. Мы на самом деле называем это со страницы обновления, чтобы получить плавный процесс обновления. Это выглядит примерно так:

A) Сценарий обновления обнаруживает, что доступна новая версия (множество способов сделать это, опрос вызовов API и т. Д. c)

B) Если пользователь принимает или истекает таймер перенаправить пользователя на upgrade страницу. Этот шаг очень важен, потому что / c вы не можете обновить работника сервиса, если приложение все еще работает. Перейдите на страницу обновления, подождите, пока сервисный работник установится, и скажите, чтобы он пропустил ожидание и перенаправил на главный экран (логин).

C) Пользователь с удовольствием запускает новую версию приложения.

Код страницы обновления: (это хорошая страница для отображения «обновляющего» пользовательского интерфейса какого-либо типа)

<script type="module">
        import { Workbox } from '/assets/workbox/workbox-window.prod.mjs';

        if ('serviceWorker' in navigator) {
            const wb = new Workbox('/serviceworker');

            // This code exists b/c a service worker can't update with just a refresh/reload in the
            // browser. This is b/c on a reload, the old and new page exist simultaneously and the old MUST
            // unload before the new service worker can automatically assume control. Also if multiple pages
            // are open, this blocks the service worker from taking control (multiple pages should not an issue with this app).
            // This code activates a waiting service worker and _then_ redirects back to the app.

            // Add an event listener to detect when the registered
            // service worker has installed but is waiting to activate.
            wb.addEventListener('waiting', (event) => {

                // Set up a listener that will reload the page as soon as the previously waiting
                // service worker has taken control.
                wb.addEventListener('controlling', (event) => {
                    window.location.replace('/login');
                });

                // Send a message telling the service worker to skip waiting.
                // This will trigger the `controlling` event handler above.
                wb.messageSW({type: 'SKIP_WAITING' });

            });

            wb.register();
        }

        // set a timeout in case the service worker has already installed.
        setTimeout(function () {
            window.location.replace('/login');
        }, 30000);
</script>

Главная страница (индекс. html, et c) (Определяет, подходит ли пользователь к приложению с готовым к активации работником сервера, поэтому для загрузки нужных ресурсов / кода требуется refre sh)

<script type="module">
        import { Workbox } from '/assets/workbox/workbox-window.prod.mjs';

        if ('serviceWorker' in navigator) {
            const wb = new Workbox('/serviceworker');

            wb.addEventListener('activated', (event) => {
                // `event.isUpdate` will be true if another version of the service
                // worker was controlling the page when this version was registered.
                if (!event.isUpdate) {
                    // service worker was updated and activated for the first time.
                    // If your service worker is configured to precache assets, those
                    // assets should all be available now.
                    // this will only happen if the browser was closed when a new version was made available
                    // and it will only happen once per service worker install.
                    // Reload to so all libs are correct version.
                    window.location.reload(true);
                }
            });

            wb.register();
        }
    </script>

...