js页面缓存的一个解决办法

      由于效率的缘故,浏览器通常会缓存js文件,这就给我们带了一个问题:当服务器端部署的项目中的js文件进行了修改后,如果再客户端不手动去刷新一次页面,js的修改效果就不会起作用,因为浏览器还是用的缓存在本地的js文件。

 

       为了解决这个问题,我们采用了这个方案,每当发布新的版本部署到服务器上的时候,我们给html页面中引用的js增加一个新的后缀,形如版本号的东西。

 

Html代码   收藏代码
  1. <script language="javascript" src="view/shell/login.js?version=20081112050245"></script>  

 

      为了自动完成这一功能,我们使用了ant,写了一个ant task来完成该项功能。

 

Java代码   收藏代码
  1. /** 
  2.  * 该任务遍历web目录,找出所有的模板文件,给js和css的引用加上版本号 
  3.  * 
  4.  * @version 1.0 2008-07-02 
  5.  * @author huangyuanmu  
  6.  * @since JDK 1.5.0_8 
  7.  */  
  8. public class AddJsAndCssVersionToVm extends Task {  
  9.   
  10.     private String path;  
  11.   
  12.     public void execute() throws BuildException {  
  13.         Date date = new Date();  
  14.         SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");  
  15.         String version = df.format(date);  
  16.         addVersionToVm(path, version);  
  17.     }  
  18.   
  19.     /** 
  20.      * 遍历web目录中的vm文件,给js和css的引用加上版本号 
  21.      * 
  22.      * @author huangyuanmu 2008-07-02 
  23.      * @param path 
  24.      */  
  25.     private void addVersionToVm(String path, String version) {  
  26.         File dir = new File(path);  
  27.         File[] files = dir.listFiles();  
  28.         if (files == null)  
  29.             return;  
  30.         for (int i = 0; i < files.length; i++) {  
  31.             if (files[i].isDirectory()) {  
  32.                 addVersionToVm(files[i].getAbsolutePath(), version);  
  33.             } else {  
  34.                 String strFileName = files[i].getAbsolutePath().toLowerCase();  
  35.                 // 如果是符合条件的文件,则添加版本信息  
  36.                 if (strFileName.endsWith(".vm")  
  37.                         || strFileName.endsWith(".html")  
  38.                         || strFileName.endsWith(".jsp")) {  
  39.                     // RandomAccessFile raf = null;  
  40.                     InputStream is = null;  
  41.                     OutputStream os = null;  
  42.                     List<String> contentList = new ArrayList<String>();  
  43.   
  44.                     // 读文件  
  45.                     try {  
  46.                         is = new FileInputStream(files[i]);  
  47.                         Reader r = new InputStreamReader(is);  
  48.                         BufferedReader br = new BufferedReader(r);  
  49.                         String line = null;  
  50.                         while ((line = br.readLine()) != null) {  
  51.                             String modLine = getModLine(line, version);  
  52.                             if (modLine != null) {  
  53.                                 line = modLine;  
  54.                             }  
  55.                             line = line + "\r\n";  
  56.                             contentList.add(line);  
  57.                         }  
  58.                         // 关闭流  
  59.                         br.close();  
  60.                         r.close();  
  61.                     } catch (Exception e) {  
  62.                         System.out.println("读文件失败");  
  63.                         e.printStackTrace();  
  64.                     } finally {  
  65.                         if (null != is) {  
  66.                             try {  
  67.                                 is.close();  
  68.                             } catch (Exception e) {  
  69.                                 e.printStackTrace();  
  70.                             }  
  71.                         }  
  72.   
  73.                     }  
  74.   
  75.                     // 写文件  
  76.                     try {  
  77.                         os = new FileOutputStream(files[i]);  
  78.                         Writer w = new OutputStreamWriter(os);  
  79.                         BufferedWriter bw = new BufferedWriter(w);  
  80.                         for (Iterator<String> it = contentList.iterator(); it  
  81.                                 .hasNext();) {  
  82.                             String line = it.next();  
  83.                             bw.write(line);  
  84.                         }  
  85.                         // 更新到文件  
  86.                         bw.flush();  
  87.                         // 关闭流  
  88.                         bw.close();  
  89.                         w.close();  
  90.                     } catch (Exception e) {  
  91.                         System.out.println("写文件失败");  
  92.                         e.printStackTrace();  
  93.                     } finally {  
  94.                         if (null != os) {  
  95.                             try {  
  96.                                 os.close();  
  97.                             } catch (Exception e) {  
  98.                                 e.printStackTrace();  
  99.                             }  
  100.                         }  
  101.                     }  
  102.                 }  
  103.             }  
  104.         }  
  105.     }  
  106.   
  107.     /** 
  108.      * 查找行中是否有js或css的引用,如果有,则加上版本号 
  109.      * 
  110.      * @author huangyuanmu 2008-07-03 
  111.      * @param line 
  112.      */  
  113.     private String getModLine(String line, String version) {  
  114.         // 增加js版本  
  115.         line.trim();  
  116.         if (line.startsWith("<script") && line.endsWith("</script>")) {  
  117.             int pos = line.indexOf(".js");  
  118.             String modLine = line.substring(0, pos) + ".js?version="  
  119.                     + version + "\"></script>";  
  120.             return modLine;  
  121.         } else if (line.startsWith("<link")  
  122.                 && line.endsWith("rel=\"stylesheet\" type=\"text/css\">")) {  
  123.             int pos = line.indexOf(".css");  
  124.             String modLine = line.substring(0, pos) + ".css?version="  
  125.                     + version  
  126.                     + "\" rel=\"stylesheet\" type=\"text/css\">";  
  127.             return modLine;  
  128.         } else {  
  129.             return null;  
  130.         }  
  131.     }  
  132.   
  133.     public void setPath(String path) {  
  134.         this.path = path;  
  135.     }  
  136. }  

 

      当然,这个程序的实现还有一些缺点。首先,模板文件中对js和css的引用必须规范,符合程序代码中描述的格式。另外,不管文件内容有没有改变,都加上了新的版本号,这会用户访问时不必要的网络流量,可能会对页面展现的速度产生一些影响。

 

      ant的build脚本文件在另外一篇中(http://huangyuanmu.iteye.com/admin/blogs/493144)。


 

新浪微博HTML头部分代码

注意上面的每个JS文件和CSS文件都加上了一个时间戳作为版本号。

<script type=”text/javascript” src=”{JS文件连接地址}?version=XXXXXXXX”></script>


<link rel=”stylesheet” type=”text/css” href=”{CSS文件连接地址}?version=XXXXXXXX”>

因为浏览器缓存的时候是以URL作为存储单位(还记得POST页面的返回按钮的问题吧?),

从而当每次首页的文件发生更新的时候只需要更改上面的版本号,就能提醒浏览器重新下载该文件了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值