ServiceWorker MIME Type Error ('text/html') on register (React)

蓝咒 提交于 2020-12-30 06:14:25

问题


The current behavior:

Service worker does not register due to the below error

The expected behavior:

Service worker registers


Details

Posted as a github issue: https://github.com/facebook/create-react-app/issues/8593

Service worker is giving the following error when attempting to register:

Error during service worker registration:
DOMException: Failed to register a ServiceWorker for scope ('http://localhost:3000/') with script ('http://localhost:3000/sw.js'):
The script has an unsupported MIME type ('text/html'). console. @ index.js:1

sw.js is showing in the sources tab of the Chrome dev tools, but not registering.

React version: 16.12.0

Error Message:

Error during service worker registration: DOMException:
Failed to register a ServiceWorker for scope ('http://localhost:3000/') with script ('http://localhost:3000/sw.js'):
The script has an unsupported MIME type ('text/html').

Failed ServiceWorker in Chrome's Inspect Tab:


Steps To Reproduce:

Register a Service Worker in React (change from unregister to register, or place SW code directly in index.html, or use a simpler SW. All cause the same error when running, in either dev or a build react app.)

SW Example:

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

Also, `http://localhost:3000/sw.js when using the default SW from React returns this HTML:

Using the code sample above returns index.html (default 404, http://localhost:3000/) when trying to access http://localhost:3000/sw.js


Suggested fixes:

Move sw.js to public folder, gives this error:


Is there a way to change the header (from text/html to application/javascript) for specifically sw.js when served to the browser in React?

I tried following some Medium articles on registering custom serviceWorkers in React, to no avail...


回答1:


When running webpack dev server, it renders default index.html for missing resource.

If you use your browser to load http://localhost:3000/sw.js, you will actually see a rendered react app (started by the index.html). That's why the mime type is html, not javascript.

This fallback to index.html is designed to support SPA with front-end routes. For example /product/123/reviews has no such html file in backend, the JS SPA app takes care of it in front-end.

Why your file is missing? I guess you created that file in the root folder of your project.

Webpack dev server doesn't serve from that root folder.

Move your sw.js into public/ folder of your project, it will be served up as expected.




回答2:


You can write code at server side to handle sw.js file. below is nodejs code which intercept sw.js file request and read from folder and send back to browser.

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



回答3:


This may be a duplicate of this one 61776698

Main think you need to know: Create the servieWorker inside public folder in order to be treated as .js file and not text/html file.

Then register that service in your index.js

Step 1, create public/sw.js

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

Step 2, create 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');
      });
    });
  }
}

Step 3, in src/index.js, add these two lines

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

You can change some things for your needs, but with those changes, you should be able to work with a custom service worker in a create-react-app application



来源:https://stackoverflow.com/questions/60500779/serviceworker-mime-type-error-text-html-on-register-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!