Modify anvil http-headers to broaden the scope of service workers?

You can already do this.

In Anvil, you can serve anything from any route, except for the _ namespace, which is reserved.
e.g. your theme assets are served from _/theme

Just create an @anvil.server.route

e.g. (in a server module)

import anvil.server
from anvil.files import data_files


@anvil.server.route("/assets/sw.js")
def sw(**params):
    headers = {
        "Content-Type": "text/javascript; charset=utf-8",
        "X-Content-Type-Options": "nosniff",
        "Cache-Control": "public, max-age=0, must-revalidate",
        "Service-Worker-Allowed": "/",
    }

    with open(data_files["sw.js"]) as f:
        return anvil.server.HttpResponse(body=f.read(), headers=headers)

Here i’ve used the files service, since the server module doesn’t have access to our app’s files without doing a network request.

I added this in native libraries


<script type="module">
    if ("serviceWorker" in navigator) {
        const url = new URL("./assets/sw.js", document.baseURI);
        navigator.serviceWorker
            .register(url, { scope: "/", updateViaCache: "none" })
            .then((sw) => {
                console.log("%cService Worker Registered", "color:green", sw);
            })
            .catch((error) => {
                console.error("Service worker registration failed:", error);
            });
    }
</script>



sw.js is a simple javascript service worker that just does some logging

// sw.js

self.addEventListener("install", (e) => {
    console.log("%cService Worker installed with scope:", "color: green", self.registration.scope);
});

self.addEventListener("activate", (e) => {
    console.log("%cService Worker activated", "color: green");
});

self.addEventListener("fetch", (e) => {
    console.log("%cService Worker fetching", "color: green", e.request.url);
});

Here’s a clone link.
If you run the app and open the browser console, you should see the service worker logs in green.

4 Likes