Ошибка регистрации Service Worker: неподдерживаемый тип MIME ('text/html')

Я использую create-реагировать-приложение с экспресс-сервером.

create-react-app имеет предварительно настроенный ServiceWorker, который кэширует локальные ресурсы (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app).

Проблема, с которой я столкнулся при попытке опубликовать на своем сервере, заключается в том, что файл service-worker.js был доступен, но я получал ошибки в консоли браузера, когда он пытался его зарегистрировать.

В Firefox я получил эту ошибку:

Ошибка при регистрации сервисного работника:

  

TypeError: ServiceWorker script at https://my-domain.com/service-worker.js for scope https://my-domain.com/ encountered an error during installation.

В Chrome я получаю более описательную ошибку:

Ошибка при регистрации работника службы: DOMException: не удалось зарегистрировать ServiceWorker: сценарий имеет неподдерживаемый тип MIME ('text/html').

Конечно, если я загляну на вкладку "Сеть" моих инструментов разработчика и найду файл service-worker.js, то увижу, что в заголовках HTTP указан неправильный тип MIME.

Я не мог понять, однако, почему он имеет неправильный тип MIME?

Ответ 1

В моем приложении Express Server у меня есть один шаблон (звездочка/*), который перенаправляется на index.html:

// Load React App
// Serve HTML file for production
if (env.name === "production") {
  app.get("*", function response(req, res) {
    res.sendFile(path.join(__dirname, "public", "index.html"));
  });
}

Это очень общий шаблон проектирования. Однако это означает, что любые запросы на неизвестные текстовые файлы сначала перенаправляются на index.html и поэтому возвращаются с типом MIME "text/html", даже если это на самом деле JavaScript или SVG или какой-либо другой файл открытого текста.

Решение, которое я нашел, заключалось в том, чтобы добавить конкретный маршрут для service-worker.js перед шаблоном подстановки:

app.get("/service-worker.js", (req, res) => {
  res.sendFile(path.resolve(__dirname, "public", "service-worker.js"));
});
app.get("*", function response(req, res) {
  res.sendFile(path.join(__dirname, "public", "index.html"));
});

Теперь, когда браузер ищет service-worker.js, Express вернет его с правильным типом MIME.

(Обратите внимание, что если вы попытаетесь добавить маршрут service-worker.js после шаблона, это не сработает, потому что маршрут подстановочного знака будет отменен.)

Ответ 2

ServiceWorker поддерживает MIME-тип: "text/javascript", application/javascript и application/x-javascript. добрался до файла сервера ur и установил

    response.writeHead(201, {
        'Content-Type': 'application/javascript'
    });

Ответ 3

Замена

'/service-worker.js'

с

'./service-worker.js'

navigator.serviceWorker.register('/service-worker.js'))

решил мою похожую проблему.

Ответ 4

Реагируйте: public/index.html

<script> 
  if ('serviceWorker' in navigator) {
    window.addEventListener('sw-cached-site.js', function() {
      navigator.serviceWorker.register('service-worker.js', {
        scope: '/',
      });
    });
  } 
  window.process = { env: { NODE_ENV: 'production' } };
</script>

Примечание: полное приложение/сайт public/sw-cached-site.js

const cacheName = 'v1';
self.addEventListener('activate', (e) =>{
  e.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cache => {
          if(cache !== cacheName) { 
            return caches.delete(cache);
          }
        })
      )
    })
  )
});
self.addEventListener('fetch', e => { 
  e.respondWith(
      fetch(e.request)
        .then(res => {
            const resClone = res.clone();
            caches
                .open(cacheName)
                .then(cache => {
                    cache.put(e.request, resClone);
                }); 
                return res;
        }).catch(err => caches.match(e.request).then(res => res))
  );
});

Ответ 5

Убедитесь, что рабочий файл сервиса создан (Chrome DevTools → Sources → Filesystem). Вы можете получить такую ошибку, если файл рабочего сервиса не сгенерирован вообще (проверьте скрипт развертывания).

Ответ 6

В случае, если вы работаете с NodeJS, файл serviceWorker должен находиться в общей папке. Если вы используете Webpack для экспорта serviceWorker в открытый доступ, вам нужно использовать "copy-webpack-plugin".

Ответ 7

Сценарий имеет неподдерживаемый тип MIME ('text/html'). Не удалось загрузить ресурс: net :: ERR_INSECURE_RESPONSE (индекс): 1 Не показано (в обещании) DOMException: не удалось зарегистрировать ServiceWorker: сценарий имеет неподдерживаемый тип MIME ('text/html').

Код для корневого файла template.js

export default ({ markup, css }) => {
  return '<!doctype html>
      <html lang="en">
        <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>MERN Marketplace</title>
          <link rel="stylesheet" href="#" onclick="location.href='https://fonts.googleapis.com/css?family=Roboto:100,300,400'; return false;">
          <link rel="stylesheet" href="#" onclick="location.href='https://fonts.googleapis.com/icon?family=Material+Icons'; return false;">

          <style>
              a{
                text-decoration: none
              }
          </style>
          <link rel="manifest" href="./manifest.json">
        </head>
        <body style="margin:0">
            <div id="root">${markup}</div>
          <style id="jss-server-side">${css}</style>
          <script type="text/javascript" src="/dist/bundle.js"></script>
          <script>
          if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('/sw.js').then(function() { 
              console.log("Service Worker Registered"); 
            });
          }
          </script>
        </body>
      </html>';
};