Serviceworker никогда не активируется и не получает сообщения, но функциональность рабочего окна работает с подпути - PullRequest
1 голос
/ 17 июня 2020

В моем текущем проекте, использующем веб-пакет с (workbox-webpack-plugin) и рабочим ящиком (с workbox-window), я обнаружил ошибку, при которой обслуживающий персонал никогда не будет отвечать на сообщения, когда страница загружается по «глубокому URL-адресу», например: / мой-путь / вложен ". Он будет работать на "/my-path" .

В минимально воспроизводимой среде это должно произойти.

  • На новой вкладке осуществляется доступ к приложению (например, через https://my-app.my-name.company-dev-envs.cloud/some-unique-id)
  • ServiceWorker регистрируется через рабочий ящик (.register())
  • после регистрации, messageSW используется для запроса «версии» SW
  • ServiceWorker отвечает, используя event.ports[0].postMessage со строкой, указывающей версию

Доступ к сайту осуществляется по «глубокому» пути, например / some-unique-id / test, обмен сообщениями никогда не будет работать.

Workbox успешно «регистрируется», но никакие события запускаться не будут (кроме externalactivated, когда Update on Reload выбрано в приложении> вкладка Service Worker). Serviceworker будет отмечен как «активный и запущенный», а другие сервисные воркеры не будут отображаться . Кажется, он тоже нормально справляется с извлечением. Только сообщения и события никогда не реагируют / не запускаются через wb экземпляр окна Workbox Window.

Вкладка «приложение» сообщает сервис-воркер как активный и запущенный: image service worker tab displaying sw correctly">

index. js (основная запись для приложения)

/* globals window, System */
import './offline';

// [...]

offline. js

import { Workbox } from 'workbox-window';

if ('serviceWorker' in navigator) {
  const wb = new Workbox('./sw.js');

  const attachDebugEventHandlers = (events) => {
    events.forEach((eventName) => {
      wb.addEventListener(eventName, () => {
        console.log(`[workbox sw] ${eventName} triggered`);
      });
    });
  };

  attachDebugEventHandlers([
    'activated',
    'controlling',
    'externalactivated',
    'externalinstalling',
    'externalwaiting',
    'installed',
    'message',
    'redundant',
    'waiting',
  ]);

  wb.register()
    .then((registration) => {
      console.log('workbox sw register successful');

      console.log("sending message")
      wb.messageSW({ type: 'GET_VERSION' }).then((ver) => console.log(`[workbox sw] version reported as ${ver}`))
    })
    .catch((err) => {
      console.error('[workbox sw] could not activate sw', err);
    });

sw. js

const SW_VERSION = '1.0.0';

console.log("sw loaded")

import {createHandlerBoundToURL, precacheAndRoute} from 'workbox-precaching';
import { NavigationRoute, registerRoute } from 'workbox-routing'

// auto generate from webpack manifest
precacheAndRoute(self.__WB_MANIFEST, {
  // Ignore all URL parameters.
  ignoreURLParametersMatching: [/.*/] // main.js is loaded with a version hash
});

self.addEventListener('message', event => {
  console.log(`[Message] event: `, event.data);
});
self.addEventListener('install', function(event) {
  event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', (event) => {
  event.waitUntil(self.clients.claim())
})

addEventListener('message', (event) => {
  console.log("message")
  if (event.data && event.data.type) {
    if (event.data.type === 'GET_VERSION') {
      event.ports[0].postMessage(SW_VERSION);
    }
  }
})

const handler = createHandlerBoundToURL('/index.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);

webpack.config. js (сокращено для краткости)

const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = {
  devtool: 'eval-source-map',
  module: {
    rules: [
      {
        test: /\.(jsx?)$/,
        include: [
          path.resolve(__dirname, 'src'),
        ],
        use: ['babel-loader'],
      },
      // [...] (style loading)
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
          },
        ],
      },
    ],
  },
  devServer: {
    historyApiFallback: true,
    disableHostCheck: true
  },
  plugins: [
    // [...]
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'src/html/index.html')
    }),
    // [...]
    new WorkboxPlugin.InjectManifest({
      swSrc: './src/sw.js',
      swDest: 'sw.js',
      maximumFileSizeToCacheInBytes: 12 * 1024 * 1024,
    }),
  ],
};

Используемые версии:

    "webpack": "^4.33.0",
    "webpack-cli": "^3.3.2",
    "workbox-window": "^5.1.3"
    "workbox-webpack-plugin": "^5.1.3"

Проверьте эту демонстрацию, чтобы увидеть проблему ( Источник )

1 Ответ

1 голос
/ 18 июня 2020

Я сам решил. Проблема, конечно, заключалась в том, что путь к ./sw.js неверен, когда пользователь переходит на подпуть.

https://my-website.com/a-subpath/a-resource не разрешает ./sw.js в https://my-website.com/sw.js, а скорее в https://my-website.com/a-subpath/sw.js

Это была очень глупая ошибка, но, надеюсь, кому-то можно помочь с этим ответом. Возможно, было бы полезно, если бы workbox-window не разрешился правильно, как если бы регистрация была успешной, а отклонил путь ./sw.js.

...