18

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: Chrome Error


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:

enter image description here

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: Public folder 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...

5
  • how are you serving sw.js? Commented Mar 4, 2020 at 16:52
  • Using serviceWorker.register() from React. Commented Mar 5, 2020 at 21:34
  • I’m saying on your web server Commented Mar 5, 2020 at 23:03
  • I'm just using the basic npm start, whichever that uses for React's default. Currently in development so haven't deployed. I've also done npm build, then serve -s build to serve the built project, but it still has the same error. Commented Mar 5, 2020 at 23:21
  • suggested workaround - deploy a production build to a local static server: npm run build && npx serve -s build Commented Oct 13, 2021 at 19:44

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

12 Comments

Also better to change .register("./sw.js") to .register("/sw.js") to avoid current route.
http://localhost:3000/sw.js responds with the code wrapped in html, and placing sw.js returns an error ERRORS: Example localhost/sw.js: imgur.com/a/EjKg8RJ || Error from placing in public: imgur.com/a/xdf772U
The sw.js is in the same spot as the default serviceWorker.js file that is bundled with create-react-app
Changing './sw.js' to /sw.js gives this error: Module not found: You attempted to import /sw which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
Update: Changing back to the code sample for the SW as above, returns index.html. However, moving to the public folder returns the error as above.
|
3

This may be a duplicate of this one 61776698

Main thing you need to know: Create the serviceWorker 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

2 Comments

the path is different than the file name (sw-build.js / sw.js). is this intentional?
Care to explain how this answer relates to the unsupported mime-type question?
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.