H5移动应用常常是一个手机网页应用,或被包装成一个安卓或苹果的应用程序。
在开发完成后,将本地开发版本上线时常常需要优化,主要的优化思路是:
- 减少交互次数,即减少对服务器的访问,主要手段有缓存优化、文件合并等。
- 减少交互数据,主要手段有文件最小化(minify)、WEB服务器配置gzip压缩等。
缓存优化
对一个典型的H5应用,如index.html,它引用了index.css, index.js等资源:
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="index.css" />
<script src="index.js"></script>
H5应用内容
</html>
默认情况下,缓存一般是这样工作的:
- 浏览器请求资源,如index.html、index.js、index.css。
- 服务器返回
200-OK
状态、文件内容以及各文件的指纹信息(比如在HTTP信息头中含有ETag值)。 - 浏览器下次请求同一资源时,带上ETag值。
- 服务器检查到该文件未变化,直接返回
304-Not Modified
状态标识文件未修改,不用返回文件内容。 - 浏览器于是直接使用本地缓存内容。
以上称为”no-cache”缓存控制策略(Cache-Control: no-cache),是很多浏览器的默认策略。
浏览器为每个资源都会询问服务器,如果服务器有更新,则下载更新(服务器返回状态200),如果没有更新,则使用本地缓存(服务器返回状态304)。
这种策略保证了资源的正确性,缺点是访问服务器次数过多。
并不是所有浏览器默认都这么办,典型的如微信浏览器,它使用复杂的检查更新策略,尽可能少的访问网络。开发者经常遇到这样的问题:
尽管服务器已更新了文件,浏览器基本不去更新,导致应用不一致或出错,而且微信检查资源更新的时机不好预测,可能过一两天再访问应用就正常了。
大多数情况下,我们看到的策略是:
- 浏览器请求资源。
- 服务器返回
200-OK
状态、文件内容以及该文件的指纹信息(比如在HTTP信息头中含有ETag值)。 - 浏览器下次请求同一资源时,直接使用本地缓存内容。
尽管效率高了,可它导致应用无法及时更新。那么问题来了,如何既能利用缓存策略减少对服务端的访问,又能及时更新应用?
建议方法是这样的:
对于应用主页(html入口文件),强制执行no-cache策略,浏览器必须每次询问是否更新。这可以通过在Web服务器上设置策略来实现,
例如使用Apache WEB服务器,可以放置.htaccess
文件中应用目录下,添加内容如下:<FilesMatch "index.html$"> Header set Cache-Control "no-cache" </FilesMatch>
对于其它被引用的文件(如css, js等),在链接的URL中添加指纹信息(HASH值,可以当作是版本号),当指纹没变时,浏览器可以不询问服务器,直接使用本地缓存。
<!DOCTYPE html> <html> <link rel="stylesheet" href="index.css?v=03cbf2" /> <script src="index.js?v=c613be"></script> H5应用内容 </html>
上面对资源引用时,URL添加了
v={HASH值}
版本标识。当文件更新时,这个值也相应变化,浏览器就会被强制要求获取更新的文件,保证及时更新。
于是,在发布应用时,我们可以用一个工具来自动为URL添加HASH值。下面以筋斗云发布优化工具webcc
为例讲解优化步骤。
注意:webcc一般与版本控制工具git配合使用。webcc是php开发的工具,请安装好php环境。
假定H5应用目录为myweb
,已添加到git版本库中。
在需要HASH的地方使用
?__HASH__
这样的格式:<!DOCTYPE html> <html> <link rel="stylesheet" href="index.css?__HASH__" /> <script src="index.js?__HASH__"></script> H5应用内容 </html>
在H5应用目录下,添加配置文件
webcc.conf.php
,配置规则如下:<?php $RULES = [ 'index.html' => 'HASH' ];
如果有多个文件需要加HASH,可以这样指定:
<?php $RULES = [ '*.html' => 'HASH', 'lib/app_fw.js' => 'HASH', ];
注意webcc配置文件是php格式,别忘记有
<?php
文件头。运行webcc(Windows环境下建议在git-bash中运行), 生成优化后的网站:
php webcc.php myweb -o myweb-online
其中myweb是H5应用的开发版本文件夹,myweb-online是生成的优化版本。
webcc生成指纹的方法是取文件sha1值的后6位。
注意几种情况:
对于预期不会变化的文件(常常在URL中已经包含版本号),是没有必要去做HASH的,比如:
<script src="jquery-1.11.1.min.js"></script> <script src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
文件不在本地,也没有办法加HASH。假如有
<script src="https://res.wx.qq.com/open/js/jweixin.js"></script>
如果该文件可能会变化,则应复制到本地后再加HASH:
<script src="js/jweixin.js?__HASH__"></script>
H5官方标准的应用缓存
熟悉H5的朋友可能知道,H5官方标准(W3C)中定义了使用manifest文件的方法用于缓存控制。
目前不建议使用,因为:
- 该方法在2011年进入草案标准,在2014年成为正式推荐标准,浏览器对其兼容性尚不完善。
- 在2016年该方案已经从W3C标准中废除。官方已不建议使用,用Service workers机制取代。