http的缓存协商

浏览器对静态文件的缓存主要是通过cache-control来控制的,cache-control可以设置no-cache,max-age以及must-revalidate等来设置缓存策略。
如果max-age> 0则会在max-age的时间内不访问服务器,用本地缓存的静态文件代替。
如果max-age<=0则会每次都询问服务器,资源文件是否有修改,有则200,无则304。这相当于f5操作。
no-cache表示不理会缓存协商,全部重新加载。这相当于是ctrl+f5操作。
must-revalidate表示必须遵循策略规则。因为浏览器有时候会提取过期的缓存,设置了这个策略后,浏览器会严格遵循客户设置的策略。
服务器在首次应答客户的request时,会返回last-modified和etag给浏览器,浏览器将cache住这些信息,下一次request服务器时就会在header里带上if-modified-since和if-non-match信息,这两个分别对应last-modified和etag。服务器会提取对应资源的modified时间和etag来做对比,如果有改变则返回200并且response last-modified和etag给客户端,没变则返回304不需要改变。
目前tomcat已经支持etag, tomcat是根据文件的contentLength和lastModified混合编码生成串儿。因为last-modified因为只支持到秒级,所以对于秒内频繁修改的静态资源效率会比较低下,etag则很好的避免了这一点。

对静态资源的处理策略

一般对于静态资源,服务器端会通过过滤机制,自动为响应的header里添加max-age信息,这样浏览器就会在本地cache住这些资源。
我们最近的一个项目,前台使用extjs,使用extjs带来的成本就是所有的页面几乎都是js页面了。因为静态js的文件量大,且我们系统的运营地点非洲网络条件不太好,带宽资源比较宝贵,不能承受频繁的静态资源请求(这里需要提一点,即使是web服务器最终响应不需要更改的304请求,对系统也是一次带宽开销,我们也想尽力避免),于是我们想通过cache-contro将js文件cache在本地。但是这就带来一个问题,对于紧急发布的一些前台界面,因为超时机制会无法及时在系统层面体现。
所以我们必须实现一种机制,在发布了新的js后,对应的引用该js的地方都要能自动刷新。所以最简单的方法就是每次编译完后生成一个版本号,然后对每个引用js的url都添加上版本号就ok。这样就可以保证在一次发布周期内始终只有一个js版本。

Extjs的动态加载策略

Extjs实现了一套动态加载策略,可以通过js语言的方式去直接引入一个资源(Ext.require),这和我们平时使用的静态引用(<script src=" xxx")是完全不同的。所以决定研究一下extjs的动态加载机制。
目前网上有开源的extjs4的源码,在动态load script时,会读取config配置信息,config可以通过loader.setConfig来配置。config里有两个参数需要注意,一个是disableCachingParam还有一个是disableCaching,后者代表是否需要为每一个请求都声称一个版本信息,前者是版本信息的参数名,默认是_dc.
loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
            if (isFileLoaded[url]) {
                return Loader;
            }
            var config = Loader.getConfig(),
                noCacheUrl = url + (config.disableCaching ? ('?' + config.disableCachingParam + '=' + Ext.Date.now()) : ''),
                isCrossOriginRestricted = false,
            
            if (!synchronous) {
                onScriptError = function() {
                    //<debug error>
                    onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
                    //</debug>
                };
                scriptElements[url] = Loader.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
            } else {
                /**
                * 组装xmlhttprequest对象,根据浏览器支持情况初始化activexobject或者xmlhttprquest
                */
                try {
                    xhr.open('GET', noCacheUrl, false);
                    xhr.send(null);
                } catch (e) {
                    isCrossOriginRestricted = true;
                }
                /**
* 伪代码,跨域失败,执行onerror回调函数
*/
                else if ((status >= 200 && status < 300) || (status === 304)
                    //<if isNonBrowser>
                    || isPhantomJS
                    //</if>
                ) {
                    //调用成功, 记录调试信息
           Ext.globalEval(xhr.responseText + debugSourceURL);
                    onLoad.call(scope);
                }
                else {
                   /**
   * 伪代码,执行onerror回调函数
   */
                }
                // Prevent potential IE memory leak
                xhr = null;
            }
        }

代码很好理解,同步时直接加载,并且通过eval方法直接执行响应的js文件(responseText),异步时则通过injectScriptElement加载,同步还是异步可以通过loader里的syncModeEnabled来设置,默认是false。
注意下这个方法里的noCacheUrl,根据disableCaching决定要不要为url加上版本信息,缓存无效时会默认以当前时间为版本号。
injectScriptElement: function(url, onLoad, onError, scope, charset) {
            var script = document.createElement('script'),
                dispatched = false,
                /**
* 设置onload和onerror的回调函数,主要是通过dispatched参数做幂等性校验
                * 为了兼容ie,script需要支持onreadystatechange事件,这个事件会又多个状态,所以需要做幂等校验
*/
            script.type = 'text/javascript';
            script.onerror = onErrorFn;
            charset = charset || config.scriptCharset;
            if (charset) {
                script.charset = charset;
            }
            //兼容ie
            if ('addEventListener' in script ) {
                script.onload = onLoadFn;
            } else if ('readyState' in script) {   // for <IE9 Compatability
                script.onreadystatechange = function() {
                    if ( this.readyState == 'loaded' || this.readyState == 'complete' ) {
                        onLoadFn();
                    }
                };
            } else {
                 script.onload = onLoadFn;
            }
            script.src = url;
            (Loader.documentHead || document.getElementsByTagName('head')[0]).appendChild(script);
            return script;
        }

该方法主要是创建了一个script的元素,url是前面方法生成的。
因为我们需要的是基于发布版本信息的缓存,所以只需要将noCacheUrl的版本信息由当前时间戳改成编译产生的版本信息即可。
最后,注意,因为extjs6做了比较大的重构,url生成挪到了ext.data.proxy.server里的buildUrl里:
url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.getCacheString(), Ext.Date.now())),搜索这一行即可。

extjs中js资源缓存策略相关推荐

  1. 前端web:浏览器静态资源缓存策略

    浏览器静态资源缓存策略 浏览器其实提供了两种控制策略,分别是强制缓存和协商缓存 强制缓存 强制缓存:就是强制使用浏览器缓存下来的资源; 在指定的一段时间内用自己缓存的文件就行,不需要再次发出请求. 具 ...

  2. 浏览器-清理页面中js的缓存

    [问题分析] 修改完 js文件中的代码后,页面刷新好几次并没有重新加载 js的文件,开始以为是文件设置没有修改成功,后来想到应该是浏览器对于 js文件的缓存机制引起的. [解决方案] 清理浏览器的缓存 ...

  3. 安卓网络数据缓存策略

    如有转载,请申明: 转载至 http://blog.csdn.net/qq_35064774/article/details/53449779 前言 对于大部分 App 来说,网络请求都是必不可少的, ...

  4. glide默认的缓存图片路径地址_手写一个静态资源中间件,加深了解服务器对文件请求的缓存策略...

    上一篇文章<详解页面静态资源的缓存策略,搞懂强缓存和协商缓存再做性能优化>我们从理论上介绍了浏览器和服务器是如何对静态资源做缓存的,这篇文章我们把它做成一个node服务器的静态资源中间件. ...

  5. html如何获取请求头变量的值。_手写一个静态资源中间件,加深了解服务器对文件请求的缓存策略...

    上一篇文章<详解页面静态资源的缓存策略,搞懂强缓存和协商缓存再做性能优化>我们从理论上介绍了浏览器和服务器是如何对静态资源做缓存的,这篇文章我们把它做成一个node服务器的静态资源中间件. ...

  6. 通过 Node.js 小示例学习浏览器缓存策略

    单纯讲一些理论性的东西可能会很难理解,本文结合一些 Node.js 小示例来学习浏览器缓存策略. 在后端为了加速服务的访问速度,通常可以使用 Memcached.Redis 做数据缓存,那么在浏览器端 ...

  7. Android中图片的三级缓存策略

    在开发过程中,经常会碰到进行请求大量的网络图片的样例.假设处理的不好.非常easy造成oom.对于避免oom的方法,无非就是进行图片的压缩.及时的回收不用的图片.这些看似简单可是处理起来事实上涉及的知 ...

  8. 总结缓存使用过程中的几种策略以及优缺点组合分析

    欢迎跳转到本文的原文链接:https://honeypps.com/cache/cache-strategy-and-relative-merits-analysis/ 今天翻译一篇关于缓存策略的文章 ...

  9. js app缓存自动刷新_如何通过清除缓存来刷新App Store中的内容

    js app缓存自动刷新 Are you finding that you're not seeing new apps on the App Store, or that updates to ap ...

最新文章

  1. SQL Server2005完全卸载
  2. usb转pci_IT-GO PCI-E转USB转接卡台式机pcie转2口usb3.0扩展卡后置集线卡
  3. go中如何使用easyjson_如何在 Go 中编写无 Bug 的 Goroutines?
  4. JS----JavaScript中数组扁平化
  5. QQ浏览器如何添加并进入书签地址?QQ浏览器添加并进入书签地址的方法
  6. 数学-矩阵计算(4)两种布局
  7. CV新赛事:口罩佩戴检测
  8. APACHE OFBIZ XML-RPC 反序列化漏洞 (CVE-2020-9496) 的复现与分析
  9. mysql5.7改了配置文件怎么生效_如何找到并修改MySQL57的配置文件m
  10. 高并发系统的限流算法
  11. 关于win10安装CPC专利软件以及win10安装office2003
  12. 小米助手版本信息测试
  13. 计算机网络:广域网的基本概念
  14. android弹出自定义layout菜单,Android:PopWindow — 对Android的底部弹窗、顶部弹窗菜单及自定义界面的使用封装...
  15. OWASP的s-sdlc项目优秀分享
  16. DCT 变换的一些思考
  17. html中word wrap,HTML的断行word-wrap: break-word 和 word-break: break-all 到底有啥区别?
  18. Py之py2neo:py2neo的简介、安装、使用方法之详细攻略
  19. Deep Learning — LeCun, Yann, Yoshua Bengio and Geoffrey Hinton
  20. C语言--实现(三)井子棋小游戏(基础版)

热门文章

  1. python3 No module named 'PIL'
  2. SpringBoot实现注册时头像上传与下载
  3. 企业架构(三)——联邦企业架构框架(FEAF)
  4. 室内空气流动原理图_家庭新风系统示意图 新风系统运行原理介绍
  5. php引用shell变量,Linux Shell Bash变量的间接引用 - Powered by PHPWind....
  6. 海外观察丨未来 10 大科技趋势预测全解读(上)
  7. 神策数据埋点大升级,一站式埋点,360° 满足你的不同场景需求
  8. MVC设计模式深入理解
  9. websocket学习和群聊实现
  10. 【NOIP2013】货车运输