NOTE: First published on Substack: https://substack.com/@andresalvareziglesias
Welcome to the second entry on the Progressive Web Application with Django series. In this chapter we will learn the basic structure of a PWA and how to implement it in Django. Let’s go!
Components of a PWA
A PWA is composed of two main elements, the Service Worker and the manifest.
The Service Worker: is the script that handles the logic of the PWA. It manages all the events of the PWA lifecycle, and the offline behavior.
The manifest: in the manifest resides the PWA description for the browser, like the name, colors and icons. This is used to show installation dialogs to the user, and to register the PWA in the browser registry,
Scopes inside a PWA
One of the settings configured in the manifest is the PWA scope. That is: what resources are available (and controllable) by this PWA.
For example, if we register a PWA with the scope /my/great/pwa/
, then:
- We will be able to add to the offline cache an image like
/my/great/pwa/images/one.png
- …but not one like
/non/pwa/images/two.png
, because is outside the configured scope.
Choosing the right scope is important because affects a lot of aspects of our PWA, like:
- Offline Functionality: By limiting the scope, you can ensure that only the necessary resources for your PWA are cached, optimizing offline performance.
- Security: A well-defined scope helps prevent unauthorized access to sensitive data or resources.
- Performance: A smaller scope can lead to faster load times, as the service worker doesn’t need to cache unnecessary files.
We can also use some HTTP headers to control the scope at server level, like the Header Set Service-Worker-allowed "/" header, but we will discuss them in the next chapters.
Implementing the PWA in Django
The basic implementation of a PWA does not require Django at all, because all the files are static javascript code and a JSON manifest. In the next chapters, we will use Django to add more power to our PWA, but le’ts start from the beginning.
The manifest file is a JSON file with the descriptor of the app and the reference to the icons and colors. There are a lot of web apps to help us with the creation of the icons, like “Manifest icons generator” (https://www.pwabuilder.com/imageGenerator).
A basic manifest file is:
{
"name": "PWA with Django",
"short_name": "PWA with Django",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#1b5e20",
"orientation": "any",
"start_url": "/",
"scope": "/",
"icons": [{
"src": "/static/demo/img/icons/icon-48x48.png",
"sizes": "48x48",
"type": "image/png"
}, {
"src": "/static/demo/img/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
}, {
"src": "/static/demo/img/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
}, {
"src": "/static/demo/img/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "/static/demo/img/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "/static/demo/img/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}]
}
After the manifest, we need to code the ServiceWorker, a javascript file responsible to handle the events of the PWA. The most basic events are “install” (when the user installs the PWA) and “activate” (when the PWA is loaded and executed).
self.addEventListener("install", (event) => {
console.info("install", event);
});
self.addEventListener("activate", (event) => {
console.info("activate", event);
});
When the man elements of the PWA are created (the manifest and the Service Worker), we need to instantiate then from the main view:
document.addEventListener('DOMContentLoaded', function() {
initializeServiceWorker();
});
function resetLog() {
document.getElementById("log").innerHTML = "";
}
function log(message) {
console.log(message);
document.getElementById("log").innerHTML += "<p>"+message+"</p>";
}
function error(message) {
console.error(message);
document.getElementById("log").innerHTML += "<p style='color: red;'>"+message+"</p>";
}
function initializeServiceWorker() {
try {
resetLog();
log("Registering service worker...");
navigator.serviceWorker.register('/serviceworker.js', {
scope: '/',
type: 'classic',
updateViaCache: 'all'
}).then(function(registration) {
log("...register completed!");
if (registration.installing) {
error("The service worker is installing, reloading...");
document.location.reload();
return;
} else if (registration.waiting) {
const sw = registration.waiting;
error("The service worker is waiting, reloading...");
document.location.reload();
return;
} else if (registration.active) {
log("The service worker is active!");
if(!navigator.serviceWorker.controller){
error("Webpage controller is still none, reloading...");
document.location.reload();
}
}
});
} catch (e) {
error(e.message);
}
}
The scripts try to register the PWA when the view is loaded. If you have followed all the steps, the screen will show something like this:
We can use Chrome Web Developer tools to check if the PWA has been registered successfully. Open the Developers Tools and click on the “Application” tab. Then, select “Service Workers” or “Manifest” in the left sidebar to display our shiny PWA:
Great, isn’t it?
In the next chapter
We now have a PWA. Now we will learn how to make an installable PWA, that will show as a native application in the operating system. That’s one of the greatest functionalities of the PWAs: we can use them to create “almost native” applications using Django.
See you in the next chapter!
About the list
Among the Python and Docker posts, I will also write about other related topics, like:
- Software architecture
- Programming environments
- Linux operating system
- Etc.
If you found some interesting technology, programming language or whatever, please, let me know! I’m always open to learning something new!
About the author
I’m Andrés, a full-stack software developer based in Palma, on a personal journey to improve my coding skills. I’m also a self-published fantasy writer with four published novels to my name. Feel free to ask me anything!
Top comments (0)