PWA 中的在线和离线资源 - 使用 Django 开发渐进式 Web 应用程序
注:首次发布于:https://andresalvareziglesias.substack.com/p/pwa-and-django-3-online-and-offline
欢迎阅读 Django 渐进式 Web 应用程序系列的第三篇。在本章中,我们将学习如何缓存 PWA 的资源,以便能够在没有活动互联网连接的情况下离线使用它们。

实现离线功能
在前面的章节中,我们定义了一个小型 PWA 应用程序,其中包含所有必需部分:清单和 ServiceWorker。我们学习了如何注册 PWA,并使用一些图像开发了一个非常简单的界面:

现在我们将学习如何将数据存储在 PWA 缓存中,以及如何选择从哪里加载每个图像:从互联网还是从本地缓存。
为了将一个或多个资源存储在 PWA 缓存中,我们在 ServiceWorker 上使用如下函数:
const CACHE_NAME = "DJANGO_PWA_TEST" const MAIN_URL = "https://laboratorio.alvarezperello.com/djangopwa/"; self.addEventListener("install", (event) => { console.info("*** PWA event *** install", event); event.waitUntil(activateApp()); }); self.addEventListener("activate", (event) => { console.info("*** PWA event *** activate", event); event.waitUntil(activateApp()); }); async function activateApp() { // When a service worker is initially registered, pages won't use it // until they next load. The claim() method causes those pages to be // controlled immediately. console.log('Claiming control...'); clients.claim().then((ev) => { console.log('...claimed!', ev); }) manageCache(); } self.addEventListener("sync", (event) => { console.info("*** PWA event *** sync", event); manageCache(); }); async function manageCache() { const cache = await caches.open(CACHE_NAME); if (!cache) { console.error("Error storing resources in cache!"); return; } storeResourceInCache(cache, MAIN_URL+"static/demo/img/snake1.jpg"); //storeResourceInCache(cache, MAIN_URL+"static/demo/img/snake2.png"); //storeResourceInCache(cache, MAIN_URL+"static/demo/img/snake3.png"); } async function storeResourceInCache(cache, element) { console.log("Storing resource in cache: "+element); cache.add(element).then(event => { console.info("Resource stored successfully! "+element); }).catch(event => { console.error("Error storing resource! "+element, event); }); }
现在,当我们执行 PWA 时,我们可以在开发者控制台中读取缓存消息:
Registering service worker... ...register completed! The service worker is active! serviceworker.js: Claiming control... serviceworker.js: Resource already in cache! static/demo/img/snake1.jpg
我们的 PWA 缓存正在运行!
选择从哪里加载每个资源
当 PWA 加载资源时,调用 fetch 事件,如下所示:
self.addEventListener("fetch", async (event) => { console.info("*** PWA event *** fetch", event); let url = event.request.url.toString(); console.info("The PWA is loading a resource from: "+url); });
我们现在可以控制请求,并可以选择从哪里返回请求的资源:从缓存或从互联网。
下面是一个示例,说明如何检查是否有缓存的资源并从缓存中返回。如果没有缓存,则从互联网请求。
self.addEventListener("fetch", async (event) => { let url = event.request.url.toString(); if (!url.includes("static/demo/img/snake")) { return false; } const cache = await caches.open(CACHE_NAME); if (!cache) { console.error("Error loading resources from cache!"); return false; } let fetchResponsePromise = await cache.match(url).then(async (cachedResponse) => { if (cachedResponse && cachedResponse.ok) { console.warn("Loading from cache: "+url); return cachedResponse; } else { console.error("Error! the cache does not have this url! "+url); console.error(cache.keys()); remoteFetchResponsePromise = await fetch(event).then(async (networkResponse) => { console.warn("Loading from internet: "+url); return networkResponse; }); return remoteFetchResponsePromise; } }); return (await fetchResponsePromise); });
我们可以读取开发者控制台来了解每个图像的加载位置,如下所示:

在下一章中
我们现在有一个 PWA。现在我们将学习如何制作可安装的 PWA,它将在操作系统中显示为本机应用程序。这是 PWA 最棒的功能之一:我们可以用它们使用 Django 创建“几乎本机”的应用程序。
下一章再见!
关于该名单
在 Python 和 Docker 文章中,我还将撰写其他相关主题,例如: