HTML5缓存机制浅析:移动端Web加载性能优化

 Web SQL Database存储机制

HTML5也提供基于SQL的数据库存储机制,用于存储适合数据库的结构化数据。根据官方的标准文档,Web SQL Database存储机制不再推荐使用,将来也不再维护,而是推荐使用AppCache和IndexedDB。

现在主流的浏览器都还是支持Web SQL Database存储机制的。Web SQL Database存储机制提供了一组API供Web App创建、存储、查询数据库。

下面通过简单的例子,演示下Web SQL Database的使用。

<script>
    if(window.openDatabase){
      //打开数据库,如果没有则创建
      var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024);
       //通过事务,创建一个表,并添加两条记录
      db.transaction(function (tx) {
           tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
           tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")');
           tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")');
       });
      //查询表中所有记录,并展示出来
     db.transaction(function (tx) {
         tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) {
             var len = results.rows.length, i;
             msg = "<p>Found rows: " + len + "</p>";
             for(i=0; i<len; i++){
                 msg += "<p>" + results.rows.item(i).log + "</p>";
             }
             document.querySelector('#status').innerHTML =  msg;
             }, null);
      });
}
</script>
<div id="status" name="status">Status Message</div><br>

将上面代码复制到sql_database.html中,用浏览器打开,可看到下面的内容。

官方建议浏览器在实现时,对每个Host的数据库存储空间作一定限制,建议默认是5MB(分Host)的配额;达到上限后,可以申请更多存储空间。另外,现在主流浏览器SQL
Database的实现都是基于SQLite。

分析:SQL Database的主要优势在于能够存储结构复杂的数据,能充分利用数据库的优势,可方便对数据进行增加、删除、修改、查询。由于SQL语法的复杂性,使用起来麻烦一些。SQL
Database也不太适合做静态文件的缓存。

在Android内嵌Webview 中,需要通过Webview设置接口启用SQL Database,同时还要设置数据库文件的存储路径。

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setDatabaseEnabled(true);
final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath();
webSettings.setDatabasePath(dbPath); <br>

Android系统也使用了大量的数据库用来存储数据,比如联系人、短消息等;数据库的格式也SQLite。Android也提供了API来操作SQLite。Web
SQL Database存储机制就是通过提供一组API,借助浏览器的实现,将这种Native的功能提供给了Web App。

2.4 Application Cache机制

Application Cache(简称AppCache)似乎是为支持Web App离线使用而开发的缓存机制。它的缓存机制类似于浏览器的缓存(Cache-Control和Last-Modified)机制,都是以文件为单位进行缓存,且文件有一定更新机制。但AppCache是对浏览器缓存机制的补充,不是替代。

先拿W3C官方的一个例子,说下AppCache机制的用法与功能。

<!DOCTYPE html>
<html manifest="demo_html.appcache">
<body>
<script src="demo_time.js"></script>
<p id="timePara"><button onclick="getDateTime()">Get Date and Time</button></p>
<p><img src="img_logo.gif" width="336" height="69"></p>
<p>Try opening <a href="tryhtml5_html_manifest.htm" target="_blank">this page</a>, then go offline, and reload the page. The script and the image should still work.</p>
</body>
</html>

上面HTML文档,引用外部一个JS文件和一个GIF图片文件,在其HTML头中通过manifest属性引用了一个appcache结尾的文件。

我们在Google Chrome浏览器中打开这个HTML链接,JS功能正常,图片也显示正常。禁用网络,关闭浏览器重新打开这个链接,发现JS工作正常,图片也显示正常。当然也有可能是浏览缓存起的作用,我们可以在文件的浏览器缓存过期后,禁用网络再试,发现HTML页面也是正常的。

通过Google Chrome浏览器自带的工具,我们可以查看已经缓存的AppCache(分Host)。

上面截图中的缓存,就是我们刚才打开HTML的页面AppCache。从截图中看,HTML页面及HTML引用的JS、GIF图像文件都被缓存了;另外HTML头中manifest属性引用的appcache文件也缓存了。

AppCache的原理有两个关键点:manifest属性和manifest文件。

HTML在头中通过manifest属性引用manifest文件。manifest文件,就是上面以appcache结尾的文件,是一个普通文件文件,列出了需要缓存的文件。

上面截图中的manifest文件,就HTML代码引用的manifest文件。文件比较简单,第一行是关键字,第二、三行就是要缓存的文件路径(相对路径)。这只是最简单的manifest文件,完整的还包括其他关键字与内容。引用manifest文件的HTML和manifest文件中列出的要缓存的文件最终都会被浏览器缓存。

完整的manifest文件,包括三个Section,类型Windows中ini配置文件的Section,不过不要中括号。

  1. CACHE MANIFEST – Files listed under this header will be cached after they
    are downloaded for the first time
  2. NETWORK – Files listed under this header require a connection to the server,
    and will never be cached
  3. FALLBACK – Files listed under this header specifies fallback pages if
    a page is inaccessible

完整的manifest文件,如:

CACHE MANIFEST
# 2012-02-21 v1.0.0
/theme.css
/logo.gif
/main.js
NETWORK:
login.asp
FALLBACK:
/html/ /offline.html <br>

总的来说,浏览器在首次加载HTML文件时,会解析manifest属性,并读取manifest文件,获取Section:CACHE MANIFEST下要缓存的文件列表,再对文件缓存。

AppCache的缓存文件,与浏览器的缓存文件分开存储的,还是一份?应该是分开的。因为AppCache在本地也有5MB(分Host)的空间限制。

AppCache在首次加载生成后,也有更新机制。被缓存的文件如果要更新,需要更新manifest文件。因为浏览器在下次加载时,除了会默认使用缓存外,还会在后台检查manifest文件有没有修改(byte
by byte)。发现有修改,就会重新获取manifest文件,对Section:CACHE MANIFEST下文件列表检查更新。manifest文件与缓存文件的检查更新也遵守浏览器缓存机制。

如用用户手动清了AppCache缓存,下次加载时,浏览器会重新生成缓存,也可算是一种缓存的更新。另外,Web App也可用代码实现缓存更新。

分析:AppCache看起来是一种比较好的缓存方法,除了缓存静态资源文件外,也适合构建Web离线 App。在实际使用中有些需要注意的地方,有一些可以说是”坑“。

  1. 要更新缓存的文件,需要更新包含它的manifest文件,那怕只加一个空格。常用的方法,是修改manifest文件注释中的版本号。如:# 2012-02-21
    v1.0.0;
  2. 被缓存的文件,浏览器是先使用,再通过检查manifest文件是否有更新来更新缓存文件。这样缓存文件可能用的不是最新的版本。
  3. 在更新缓存过程中,如果有一个文件更新失败,则整个更新会失败。
  4. manifest和引用它的HTML要在相同Host。
  5. manifest文件中的文件列表,如果是相对路径,则是相对manifest文件的相对路径。
  6. manifest也有可能更新出错,导致缓存文件更新失败。
  7. 没有缓存的资源在已经缓存的HTML中不能加载,即使有网络。例如:https://appcache-demo.s3-website-us-east-1.amazonaws.com/without-network/。
  8. manifest文件本身不能被缓存,且manifest文件的更新使用的是浏览器缓存机制。所以manifest文件的Cache-Control缓存时间不能设置太长。

另外,根据官方文档,AppCache已经不推荐使用了,标准也不会再支持。现在主流的浏览器都是还支持AppCache的,以后就不太确定了。

在Android内嵌Webview中,需要通过Webview设置接口启用AppCache,同时还要设置缓存文件的存储路径,另外还可以设置缓存的空间大小。

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setAppCacheEnabled(true);
final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
webSettings.setAppCachePath(cachePath);
webSettings.setAppCacheMaxSize(5*1024*1024);<br>

本文文字及图片出自 CSDN

你也许感兴趣的:

共有 1 条讨论

  1. 大哥你讲的两种缓存方式都是不推荐的方式了。你最后又没有讲推荐的方式是什么,读完这文章就感觉话说了一半就没有了一样。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注