动态触发HTML5缓存清单文件?

21
我正在使用HTML5的新缓存清单功能来缓存我的Web应用程序,以便离线工作。 当页面加载时,以下HTML元素会自动缓存内容:
<html lang="en" manifest="offline.manifest">

这个工作正常。但是,我想给我的用户提供选择是否要将内容缓存离线的选项。因此,这是我的问题:

是否有任何方法在运行时使用JavaScript触发应用程序被缓存,并且不是在页面加载时自动完成。

例如,类似于这样的内容(使用jQuery):

----------------index.html--------------

<head>
 <meta charset="utf-8" />

 <script src="http://code.jquery.com/jquery-1.4.4.min.js"></script> 
 <script type="text/javascript" src="Main.js"></script> 

</head>
<body>

 <button id="cacheButton">Cache Page</button>

</body>
</html>

---------Main.js---------

$(document).ready(
 function()
 {
  $('#cacheButton').click(onCacheButtonClick);
 }
)

function onCacheButtonClick(event)
{
 console.log("Setting Offline Manifest");
 $('#htmlRoot').attr("manifest","offline.manifest");
}

-------------离线.manifest-------------

CACHE MANIFEST

#version .85

#root
index.html
scripts/main.js

#jquery assets
http://code.jquery.com/jquery-1.4.4.min.js

基本上,当按钮被点击时,我会动态设置HTML元素的清单属性。 这是有效的(在元素被设置的意义上),但不会导致浏览器缓存页面。

有什么建议吗?


Firefox在缓存之前会提示(即您想要的功能已内置)。其他浏览器不确定。 - Shane Daniel
谢谢。Safari和Google Chrome似乎不会提示,至少在Mac和iOS上不会。 - mikechambers
我希望这也能够正常工作。 - forresto
你尝试过这个吗?<script>document.write('<html manifest=offline.appcache">');</script> - Pitipong Guntawong
虽然有点晚了,但如果有人在2021年遇到这个问题:创建渐进式Web应用程序(PWA)可能是现在处理此场景的最佳方式。 - Marcel
显示剩余2条评论
4个回答

10

通过添加指向包含实际缓存清单的空页面的 iframe,可以动态触发缓存。

offline.html:

<!DOCTYPE html>
<html manifest="offline.appcache">
<head>
    <title></title>
</head>
<body>
</body>
</html>

请确保将index.html添加到缓存清单中。 然后只需添加类似于以下内容:

<iframe src="offline.html" width="0" height="0">

动态地将内容添加到document.body以触发缓存。


1
是的,这确实会触发缓存。但当父页面尝试访问缓存资源时,它会错过缓存并发出真正的请求。(在Chrome 39中测试过。)因此,这样做没有任何好处。 - bioneuralnet

5
经过多周的离线缓存,答案是否定的,你要么进行缓存,要么不进行缓存,在客户端设置缓存属性没有效果。
你可以考虑为缓存版本提供替代url,但请注意该页面也会作为“主入口”隐式缓存。
我不明白为什么你想要离线缓存jquery,因为它很可能已经被服务端以非常长的到期时间提供了。
你可以考虑使用离线存储作为替代方案。将脚本的文本存储起来,并在加载时将其注入到DOM中。如果没有被缓存,则使用Ajax获取并注入响应,因为使用src创建脚本标签不会加载脚本。

7
如果您希望在浏览器离线时仍然可以使用Web应用程序,则可能需要离线缓存jQuery。将JavaScript代码源放入离线存储可能是实现此目标的错误方式,正确的方法是使用缓存清单。 - 1800 INFORMATION
1
我最终采用的方法是创建一个按钮,上面写着“使用/获取离线缓存”,点击后跳转到另一个HTML文件,该文件与原文件完全相同,但包含了manifest。我发现用户甚至更喜欢这种方式,因为他们可以知道自己是在线还是离线状态。利用缓存的javascript事件,你甚至可以添加一个进度条,向用户显示下载进度(已完成的文件数量),以及缓存是否已经更新。 - Myforwik
你必须在清单中缓存jQuery。浏览器缓存可以随时清除,因此不可靠。这对移动浏览器(内存较少)尤其有问题。 - markmarijnissen

0

有一件事情你必须记住,不要缓存清单文件本身。所以你需要做的就是根据用户选择使用不同版本的清单文件来刷新页面。你可以动态生成清单文件本身,对该文件的任何更改都会导致缓存刷新。最佳实践是通过更改清单文件的版本来触发重新缓存,例如:# ver1 - 01/01/2018 到 # ver2 - 02/02/2018 就可以解决问题。因此,你不能在客户端更改它,但可以在服务器端进行更改。


在DreamWeaver中,我使用以下注释来自动修改清单文件:#<!-- #BeginDate format:IS1m -->2017-10-19 17:50<!-- #EndDate --> - MarkMYoung

0
根据您的应用程序,可能可以使用修改版的@schibum方法,通过将您的应用程序拆分为“迷你”应用程序,然后在iframe中缓存子部分。考虑以下示例:

index.html

<html manifest="indexx.manifest">
<head>
    <script src="jquery-2.1.4.min.js"></script>
    <script src="index.js"></script>
    <title>Index</title>
</head>
<body>
    <ul>
        <li><a href="1.html">One</a>
        <li><a href="2.html">Two</a>
        <li><a href="3.html">Three</a>
    </ul>
    <iframe id="if" />
</body>
</html>

index.manifest

CACHE MANIFEST
# 3
index.html
jquery-2.1.4.min.js 
index.js

index.js

$( document).ready(function() {
    var pages = ['1.html','2.html','3.html'];
    var LoadNext = function() {
        alert(pages[0]);
        page = pages.shift();
        alert(page)
        if ( page !== undefined ) {
            console.log("Attempting to load " + page);
            $('#if').attr('src', page)
        } else {
            console.log("All done");
        }
    };
    $('#if').load(function() {
        console.log("Finished loading");
        LoadNext()
    });
    LoadNext(); 
});

1.html

<html manifest="1.manifest">
<head>
    <title>One</title>
</head>
<body>
    <img src="1.jpg" width="50%">
</body>
</html>

1.manifest

CACHE MANIFEST
# 2
1.html
1.jpg

{2,3}.{html,manifest} 遵循 1.{html,manifest} 的形式。

因此,每个子页面(1.html、2.html、3.html)都有自己的清单,因此它们可以独立地缓存。index.html 有自己的(最小)清单,因此无条件地缓存它不像缓存整个应用程序那样占用网络带宽。然后,JavaScript 负责预加载 iframe 中的每个页面,以便将其缓存。

加载 index.html,然后脱机查看子页面如何工作。也一样。

一个明显的缺点是在页面之间共享的任何资源(例如 jQuery)必须被冗余地缓存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接