服务工作者注册错误:不支持的MIME类型(' text / html')

时间:2018-03-29 22:40:21

标签: javascript reactjs express service-worker create-react-app

我将create-react-appexpress服务器一起使用。

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:范围https://my-domain.com/service-worker.js https://my-domain.com/的ServiceWorker脚本在安装过程中遇到错误。

  

在Chrome上,我收到了更具描述性的错误:

  

服务工作者注册期间出错:DOMException:无法注册ServiceWorker:脚本的MIME类型不受支持(' text / html')。

果然,如果我查看开发人员工具的“网络”选项卡并搜索service-worker.js文件,我可以看到HTTP标头中的MIME类型错误。

我无法理解为什么它的MIME类型错误?

15 个答案:

答案 0 :(得分:7)

在我的Express服务器应用程序中,我有一个重定向到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路由,它将无法正常工作,因为通配符路由将覆盖。)

答案 1 :(得分:7)

我认为if (!String.prototype.replaceAll) { String.prototype.replaceAll = function(search, replace){ return this.split(search).join(replace); } } 中不存在服务工作者文件,因此服务器将返回index.html。然后,注册功能不知道如何处理index.html文件,并告诉您MIME类型不正确。

一种快速的解决方法是将service-worker.js文件复制到n = 4 # for reading from 5th line with open("write.txt",'r') as t: for i,line in enumerate(t): if i >= n: # i == n-1 for nth line print(line) 文件夹中,这样,当您点击Select * from table where id in (select distincnt(id) from table ); 时,便会在浏览器中看到该文件。

请记住,请转到ChromeDev>应用程序> ServiceWorkers,然后点击取消订阅。为了删除错误的。记住还要禁用缓存

答案 2 :(得分:2)

ServiceWorker支持的MIME类型是“文本/ javascript”,应用程序/ javascript和应用程序/ x-javascript。进入您的服务器文件并设置

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

答案 3 :(得分:2)

替换

'/service-worker.js'

使用

'./service-worker.js'

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

解决了我的类似问题。

答案 4 :(得分:1)

确保已生成服务辅助文件(Chrome DevTools->源->文件系统)。如果根本没有生成服务工作者文件,则可能会收到此类错误(请检查您的部署脚本)。

答案 5 :(得分:1)

如果您正在使用NodeJS,则serviceWorker文件应放在公共文件夹中。 如果您使用Webpack将serviceWorker导出到公共场所,则需要使用“ copy-webpack-plugin”。

答案 6 :(得分:1)

我使用nginx来服务react app,我解决了向nginx添加mime类型的问题:

http {
    include    mime.types; // <--- this line

    # another config details
}

您还可以找到mime.types file here

答案 7 :(得分:1)

就我而言,对于Vue,我需要使用如下所述的命令行工具在公共目录中生成mockServiceWorker.js:

https://mswjs.io/docs/getting-started/integrate/browser

从我的样品中还不清楚。具体来说,要运行的CLI命令是:

npx msw init ./public

答案 8 :(得分:0)

反应:  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))
  );
});

答案 9 :(得分:0)

我遇到了同样的问题,并且从配置中删除了其他firebase库,对我来说Check this on Github


// Change this 
var firebaseConfig = {
    apiKey: "*********",
    authDomain: "**********",
    databaseURL: "*********",
    projectId: "***********",
    storageBucket: "************",
    messagingSenderId: "***********",
    appId: "************"
};

// To =>
var firebaseConfig = {
  apiKey: "*****************",
  projectId: "**********",
  messagingSenderId: "*******",
  appId: "***********"
};

答案 10 :(得分:0)

运行 webpack 开发服务器时,它会为缺少的资源呈现默认的 index.html。

如果您使用浏览器加载 http://localhost:3000/sw.js,您实际上会看到一个渲染的 React 应用程序(由 index.html 启动)。这就是为什么 mime 类型是 html,而不是 javascript。

这种对 index.html 的回退旨在通过前端路由支持 SPA。例如 /product/123/reviews 在后端没有这样的 html 文件,JS SPA 应用程序会在前端处理它。

为什么你的文件丢失了?我猜您在项目的根文件夹中创建了该文件。

Webpack 开发服务器不从该根文件夹提供服务。

将您的 sw.js 移动到您项目的 public/ 文件夹中,它将按预期提供。

答案 11 :(得分:0)

我猜,Service Worker 文件应该在根路径上。就我而言,我不能使用根路径,所以我使用 apache 重定向规则将 service-worker.js 重定向到我的子路径。

 RewriteRule "^/service-worker.js$"  "/sub/service-worker.js"

答案 12 :(得分:0)

我在用 python 托管网站时遇到了类似的问题。这里的任何解决方案都不适合我,我遇到了一个 bug posted in chrome dev forum,它设法解决了我的问题。显然,在我的情况下,这是与 Windows 相关的问题,因为 .js 文件的注册表项将内容类型设置为 text/plain 由于某些先前的配置,我不得不改回 application/javascript。

TLDR:

  1. 打开注册表编辑器
  2. 转到计算机\HKEY_CLASSES_ROOT\.js
  3. 将内容类型更改为 application/javascript
  4. 重新启动 Chrome 并运行您的网站

希望这对某些人有所帮助,以防上述方法均无效。

答案 13 :(得分:-1)

该脚本具有不受支持的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="https://fonts.googleapis.com/css?family=Roboto:100,300,400">
          <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

          <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>`;
};

答案 14 :(得分:-1)

self.addEventListener('fetch', function(event) {});

在您的service-worker.js文件中添加上述代码