1

I'm trying to get my first service worker registered on a Heroku app. Front end has been built using create-react-app, backend uses Django on the same server. I've made a basic "hello world" service worker which works in development, but gives a 404 error in production. I think I might be misunderstanding the basic file system that I'm using in production.

My file system on my local directory essentially looks like this:

root
 - public
    - index.html
    - sw.js
    static
     - manifest.json
 - src
    - app.js
    - serviceWorker.js
...

serviceWorker.js checks the browser and then attempts to register the service worker:

...
navigator.serviceWorker
  .register(`${process.env.PUBLIC_URL}/sw.js`)
  .then(registration => {
...
//process.env.PUBLIC_URL returns http://localhost:3000/ in development, and https://www.mydomain.app/ in production

sw.js just contains dummy code:

self.addEventListener('install', function(event) {
  console.log("Hello World")
})

When this is deployed to Heroku, yarn build packages everything into a build directory, which looks like:

build
 - index.html
 - sw.js
 - service-worker.js // added automatically by web-pack
 - asset-manifest.json // added automatically by web-pack
 - precache-manifest.xyz.js // added automatically by web-pack
 - static
    - css
    - js
    - manifest.json

In production, this fails to find the file sw.js during the register() function. The same error is happening with the auto-generated service-worker.js, where it works in development but not in production (404):

"TypeError: Failed to register a ServiceWorker for scope ('https://www.mydomain.app/') with script ('https://www.mydomain.app/sw.js'): A bad HTTP response code (404) was received when fetching the script."

I think my use of PUBLIC_URL is correct, as it works in development and production to find manifest.json at<link rel="manifest" href="%PUBLIC_URL%/static/manifest.json" />. I've checked the file system by using heroku run bash and everything seems to be in the right place, what am I missing?

halfer
  • 19,824
  • 17
  • 99
  • 186
Colgato
  • 11
  • 3

1 Answers1

0

Found the answer here, maybe this will help someone else.

I needed to serve the sw.js file as a view with django urls:

from django.views.generic.base import TemplateView
urlpatterns = [ 
    ...   
    path('sw.js', TemplateView.as_view(template_name="sw.js", 
    content_type='application/javascript'), name='sw.js'),
    ...
]
Colgato
  • 11
  • 3