缓存动态视图 PWA ASP

Posted

技术标签:

【中文标题】缓存动态视图 PWA ASP【英文标题】:caching a dynamic view PWA ASP 【发布时间】:2019-12-29 09:01:35 【问题描述】:

我对 PWA 中的缓存有疑问。 我想让用户选择一个要缓存的列表。例如: 用户创建了几个列表,然后他选择了一个,以保存以供离线使用。 当他离线时,他只能打开 2 个视图:

    诸如“你离线,你想打开保存的列表吗?”之类的。 (如果存在) 查看已保存的列表。

此时,我正在缓存用户访问过的所有视图,但无法缓存包含动态数据的视图。 我正在使用 PWA.essentials 来做 PWA。

     services.AddProgressiveWebApp(new PwaOptions
            
                RegisterServiceWorker = true,
                RegisterWebmanifest = false,
                Strategy = ServiceWorkerStrategy.NetworkFirst,
                RoutesToPreCache = "/, /Home/Offline, /Home/Saved_list",
                OfflineRoute="Offline.html"
            ); 

我已经创建了 manifest.json。当我在 chrome 中使用开发模式时,我可以看到,此时,我正在缓存所有视图,除了路径更复杂的视图(如 /Controller/View/something)。

我正在保存列表,该用户在“Offline.json”文件中选择,该文件也被缓存,但是当用户更改列表以保存时,文件“offline.json”仍然没有更新。我的意思是我的 PWA 不会用新的 PWA 替换它。

所以我有一个关于如何将动态列表保存到浏览器缓存,然后设置离线路由到它的问题。

由 pwa.essentials 创建的 Service Worker:

(function () 
    'use strict';

    // Update 'version' if you need to refresh the cache
    var version = 'v1.0::NetworkFirst';
    var offlineUrl = "Offline.html";

    // Store core files in a cache (including a page to display when offline)
    function updateStaticCache() 
        return caches.open(version)
            .then(function (cache) 
                return cache.addAll([
                    offlineUrl,
                    '/','/Home','/Generate/Select_mode'
                ]);
            );
    

    function addToCache(request, response) 
        if (!response.ok)
            return;

        var copy = response.clone();
        caches.open(version)
            .then(function (cache) 
                cache.put(request, copy);
            );
    

    self.addEventListener('install', function (event) 
        event.waitUntil(updateStaticCache());
    );

    self.addEventListener('activate', function (event) 
        event.waitUntil(
            caches.keys()
                .then(function (keys) 
                    // Remove caches whose name is no longer valid
                    return Promise.all(keys
                        .filter(function (key) 
                            return key.indexOf(version) !== 0;
                        )
                        .map(function (key) 
                            return caches.delete(key);
                        )
                    );
                )
        );
    );

    self.addEventListener('fetch', function (event) 
        var request = event.request;

        // Always fetch non-GET requests from the network
        if (request.method !== 'GET') 
            event.respondWith(
                fetch(request)
                    .catch(function () 
                        return caches.match(offlineUrl);
                    )
            );
            return;
        

        event.respondWith(
            fetch(request)
                .then(function (response) 
                    // Stash a copy of this page in the cache
                    addToCache(request, response);
                    return response;
                )
                .catch(function () 
                    return caches.match(request)
                        .then(function (response) 
                            return response || caches.match(offlineUrl);
                        )
                        .catch(function () 
                            if (request.headers.get('Accept').indexOf('image') !== -1) 
                                return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>',  headers:  'Content-Type': 'image/svg+xml'  );
                            
                        );
                )
        );

    );

)();

【问题讨论】:

【参考方案1】:

您正在将用户选择的页面列表保存在服务器端的 offline.json 中,并且您也在缓存该文件。根据 PWA 的工作,缓存资源是从缓存而不是从服务器提供的,直到缓存被删除/清除。

您可以采取 2 种方法。

    每当用户添加到offline.json 时,您需要强制服务工作者更新离线文件。

    您可以简单地将用户选择的内容存储在本地存储中,然后从那里将页面添加到缓存列表中。

【讨论】:

你是否根据用户选择修改json文件? 此时我正在创建像 c# JsonSerializer serializer = new JsonSerializer(); string json = JsonConvert.SerializeObject(currentList); string path = "./wwwroot/OfflineList.json"; System.IO.File.WriteAllText(path, json); 这样的 json,并使用 PWA Essentials 自动创建的 Service Worker。它不会再次缓存它,它只是在应用启动时缓存它。 是的,当用户选择列表时,我正在从offline.json中删除所有数据并在那里写入新列表。 当您缓存离线文件时,您需要在文件更新时更新缓存。看看这是否有帮助***.com/questions/33262385/… 但是如何缓存来自具有更复杂路径的视图或将参数作为输入的视图的数据。此时,例如我正在缓存 ID X 的列表,当我离线时我无法打开它,即使它在我的缓存中。所以我想用动态数据创建新的,我将发送例如“上次访问的列表”或我之前提到的用户选择的列表。

以上是关于缓存动态视图 PWA ASP的主要内容,如果未能解决你的问题,请参考以下文章

详解Asp.Net Core 2.1+的视图缓存(响应缓存)

ASP.NET MVC 视图和控制器输出缓存

ASP.NET MVC 阻止当前请求的视图页面缓存OutputCache

ASP.NET MVC:动态添加部分视图并将它们反映在视图模型中

如何缓存将图像返回到asp.net mvc中的视图的操作方法的输出?

C# ASP.NET MVC:动态更新视图