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 文章中,我还将撰写其他相关主题,例如: