注册时的 ServiceWorker MIME 类型错误('text/html')(React)

Posted

技术标签:

【中文标题】注册时的 ServiceWorker MIME 类型错误(\'text/html\')(React)【英文标题】:ServiceWorker MIME Type Error ('text/html') on register (React)注册时的 ServiceWorker MIME 类型错误('text/html')(React) 【发布时间】:2020-06-15 10:53:01 【问题描述】:

当前行为:

由于以下错误,Service Worker 未注册

预期行为:

Service Worker 注册


详情

作为 github 问题发布: https://github.com/facebook/create-react-app/issues/8593

Service Worker 在尝试注册时出现以下错误:

Service Worker 注册时出错: DOMException: 无法使用脚本 ('http://localhost:3000/sw.js') 为范围 ('http://localhost:3000/') 注册 ServiceWorker: 该脚本具有不受支持的 MIME 类型 ('text/html')。 安慰。 @index.js:1

sw.js 显示在 Chrome 开发工具的源选项卡中,但未注册。

反应版本:16.12.0

错误信息:

Service Worker 注册期间出错:DOMException: 使用脚本 ('http://localhost:3000/sw.js') 为范围 ('http://localhost:3000/') 注册 ServiceWorker 失败: 该脚本具有不受支持的 MIME 类型('text/html')。

Chrome 的检查选项卡中的 ServiceWorker 失败:


复制步骤:

在 React 中注册一个 Service Worker(从取消注册更改为注册,或者将 SW 代码直接放在 index.html 中,或者使用更简单的 SW。在开发或构建 react 应用程序中运行时都会导致相同的错误。)

软件示例:

export function register() 
  if ("serviceWorker" in navigator) 
    navigator.serviceWorker
      .register("./sw.js")
      .then(function(registration) 
        // Successful registration
        console.log(
          "Hooray. Registration successful, scope is:",
          registration.scope
        );
      )
      .catch(function(error) 
        // Failed registration, service worker won’t be installed
        console.log(
          "Whoops. Service worker registration failed, error:",
          error
        );
      );
  


此外,`http://localhost:3000/sw.js 在使用 React 的默认 SW 时会返回此 HTML:

使用上面的代码示例在尝试访问http://localhost:3000/sw.js 时返回 index.html(默认 404,http://localhost:3000/)


建议的修复:

sw.js 移动到公用文件夹,出现此错误:


当在 React 中提供给浏览器时,有没有办法将标头(从 text/html 更改为 application/javascript)专门用于 sw.js

我尝试关注一些关于在 React 中注册自定义 serviceWorkers 的 Medium 文章,但无济于事......

【问题讨论】:

sw.js 的服务怎么样? 使用 React 中的 serviceWorker.register()。 我在你的网络服务器上说 我只是在使用基本的 npm start,无论哪个用于 React 的默认值。目前正在开发中,因此尚未部署。我也做过npm build,然后serve -s build 为构建好的项目服务,但还是报同样的错误。 建议的解决方法 - 将生产版本部署到本地静态服务器:npm run build && npx serve -s build 【参考方案1】:

在运行 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/ 文件夹中,它将按预期提供。

【讨论】:

最好将.register("./sw.js") 更改为.register("/sw.js") 以避开当前路线。 http://localhost:3000/sw.js 以 html 中包裹的代码响应,放置 sw.js 会返回错误 ERRORS: Example localhost/sw.js: imgur.com/a/EjKg8RJ ||公开发布错误:imgur.com/a/xdf772U sw.js 与 create-react-app 捆绑的默认 serviceWorker.js 文件位于同一位置 './sw.js' 更改为 /sw.js 会出现此错误:找不到模块:您尝试导入项目 src/ 目录之外的 /sw。不支持 src/ 之外的相对导入。 更新:改回上述 SW 的代码示例,返回 index.html。但是,移动到公用文件夹会返回如上的错误。【参考方案2】:

这可能是这个61776698的副本

你需要知道的主要事情:在公共文件夹中创建 serviceWorker 以便被视为 .js 文件而不是 text/html 文件。

然后在 index.js 中注册该服务

第一步,创建public/sw.js

self.addEventListener('message', async (event) => 
  console.log('Got message in the service worker', event);
);

第二步,创建src/sw-register.js

export default function LocalServiceWorkerRegister() 
  const swPath = `$process.env.PUBLIC_URL/sw-build.js`;
  if ('serviceWorker' in navigator && process.env.NODE_ENV !== 'production') 
    window.addEventListener('load', function () 
      navigator.serviceWorker.register(swPath).then(registration => 
        console.log('Service worker registered');
      );
    );
  

第三步,在src/index.js中,添加这两行

import LocalServiceWorkerRegister from './sw-register';
...
LocalServiceWorkerRegister();

您可以根据需要更改一些内容,但是通过这些更改,您应该能够在 create-react-app 应用程序中使用自定义服务工作者

【讨论】:

路径与文件名不同 (sw-build.js / sw.js)。这是故意的吗?【参考方案3】:

您可以在服务器端编写代码来处理 sw.js 文件。下面是拦截 sw.js 文件请求并从文件夹中读取并发送回浏览器的 nodejs 代码。

app.get('/sw.js', (req, res) => 
  if (__DEVELOPMENT__) 
    http.get('http://localhost:4001/static/build/sw.js', (r) => 
      res.set(
        'Content-Type': 'text/javascript',
        'Cache-Control': 'max-age=0, no-cache, no-store, must-revalidate'
      );
      r.setEncoding('utf8');
      r.pipe(res);
    ).on('error', (e) => 
      console.error(`Error in sending sw.js in dev mode : $e.message`);
    );
   else 
    res.setHeader('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
    res.sendFile('sw.js',  root: path.join(__ROOT_DIRECTORY__, 'assets', 'build') ); // eslint-disable-line no-undef
  
);

【讨论】:

以上是关于注册时的 ServiceWorker MIME 类型错误('text/html')(React)的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 无法使用脚本为范围注册 ServiceWorker,该脚本具有不受支持的 MIME 类型

FirebaseError browserErrorMessage:“无法注册 ServiceWorker:ServiceWorker 脚本评估失败”

注册 ServiceWorker 返回 AbortError code:20

在浏览器中出现错误 - 无法为范围注册 ServiceWorker

将 Firebase FCM 添加到 reactjs 应用程序

“未捕获(承诺)的DOMException:无法为范围注册ServiceWorker”-脚本资源位于重定向后面,不允许使用