4

I'm creating a website using Python's micro-framework Flask. I recently found out about Progressive Web Apps and I'm trying to experiment with it. From what I understand I have to (amongst other things) register a service worker. This is what I'm getting stuck on. I'm using a base.html template that extends to my other .html templates which get rendered by Flask. In my base.html file I've inculded this code:

<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register("service-worker.js").then(function(registration) {
    // Registration was successful
    console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
  // registration failed :(
     console.log('ServiceWorker registration failed: ', err);
   });
 });
}
</script>

I know that this won't work because the service-worker.js file needs to be in the same directory as the html file is, but because they are getting rendered by Flask I don't know in what directory I need to place the service-worker.js file for it to work. I've tried putting it in the same directory where my templates are located and also in the root folder (and then point to that location in the register script), but that doesn't work.

The Python files are located in the websites root folder. The template folder that contains the html files is also located in the root folder - aswell as the static folder which holds css/js/images.

So my question is, is it possible to register a service worker (or create a PWA at all) using Flask as a back-end? If so, how do I register it? Thank you in advance!

Edit:

I'm not sure why my question was marked duplicate. I'm not trying to serve the service worker from my /static/js folder. As I said above, as for as I understand it, the service-worker.js file needs to be located in the same location as the html file it's referencing from. Unless I'm missing something I don't know how that's the same question as how to link static files using url_for.

Classi
  • 175
  • 2
  • 7

2 Answers2

5

Using Flask, with your sw.js file in the static folder but outside the js folder, I managed to get a work around in the routes using make_response from flask

I wrote the following code as the route to the sw.js

from flask import make_response, send_from_directory
@app.route('/sw.js')
def sw():
    response=make_response(
                     send_from_directory('static',filename='sw.js'))
    #change the content header file. Can also omit; flask will handle correctly.
    response.headers['Content-Type'] = 'application/javascript'
    return response

Edit this line from

navigator.serviceWorker.register("service-worker.js").then(function(registration) {

To :

navigator.serviceWorker.register("/sw.js").then(function(registration) {

You can also specify scope; the scope the service worker should cover like this :

navigator.serviceWorker.register("/sw.js", {scope:"/"}).then(function(registration) {

REMEBER : sw.js referes to the file you named service-worker.js

Complete code for base.html inline js would be :

<script>     
if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register("/sw.js", { scope: '/' })
        .then(function(registration) {
          // Registration was successful
          console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
          // registration failed :(
          console.log('ServiceWorker registration failed: ', err);
        });
      });
    } 

Complete code for app.py would be same as above example

And don't forget your route @app.route("/sw.js")

Let me know if this helps

Michael Elimu
  • 61
  • 2
  • 7
  • 1
    I am trying to use this method (by adding HTTP header **Service-Worker-Allowed**) to expand the scope of my service-worker to `"/"`, but this route is never called. Any pointers? – Chanticleer Aug 22 '20 at 08:35
0

For this issue

I know that this won't work because the service-worker.js file needs to be in the same directory as the html file is, but because they are getting rendered by Flask

Not necessary at least if you use Google's workbox library which allows to create a specific mapping, called precacheManifest within the service workers js file, more info here https://developers.google.com/web/tools/workbox/modules/workbox-build.

However, you cannot achieve full offline mode, if you have dynamic content rendered server side, which applies in Flask. This approach abbreviated as SSR according to documentation provided in the link https://developers.google.com/web/ilt/pwa/introduction-to-progressive-web-app-architectures is not well suited for registering service-workers. What you want to do as a next step, is to migrate to a new architecture called app-shell. Basically, you create a static html which you populate using api calls, then you can cache gradually your website.

aarsakian
  • 13
  • 2