美文网首页
利用Localstorage进行JS缓存

利用Localstorage进行JS缓存

作者: 小漠穷秋 | 来源:发表于2017-11-10 16:40 被阅读0次

    目的:

    利用localstorage进行关键Js和CSS缓存,节约下载。

    知识点:

    1.浏览器默认缓存机制
    2.Localstorage
    3.异步改造为同步

    讲解:

    1.浏览器默认会对JS进行缓存。使得下一次进入的时候变为304请求。然而,用户重新刷新等操作时,浏览器会清除这些缓存。所以这些缓存是不可控的。
    2.Localstorage的大小大约在5M。
    3.异步下载要想保证顺序,可以采用递归的方式。

    设计框架:

    image.png

    代码实现:

    window.Xhrfactory = function() {
    this.init();
    }
    window.Xhrfactory.prototype = {
    init: function() {
    this.xhr = this.create();
    },
    create: function() {
    var xhr = null;
    if(window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
    xhr = new ActiveXObject('Msml2.Xmlhttp'); //IE7及以后版本IE
    }
    else {
    xhr = new ActiveXobject('Microsoft.Xmlhttp');//其他版本IE
    }
    return xhr;
    },
    readystate: function(callback) {
    this.xhr.onreadystatechange = function(){
    if(this.readyState === 4 && this.status === 200) { //this发生了默认绑定,指向了xhr
    callback(this.responseText);
    console.log(this);
    }
    }
    },
    para: function(data) {
    var datastr = '';
    if(data && Object.prototype.toString.call(data) === "[object object]") { //判断对象是否为对象
    for(var i in data) {
    for (var i=0;i<length;i++){
    datastr += i + '='
    data[i] + '&';
    }
    }
    datastr = '?' + datastr;
    }
    return datastr;
    },
    get: function(url,data,callback) {
    this.readystate(callback);
    var newurl = url;
    var datastr = this.para(data);
    newurl = url + datastr;
    this.xhr.open('get',newurl,false);//这里不能使用true 需要使用false来解决异步问题
    this.xhr.send();
    }
    };

    var localStorageSign = 'on'; //后台开关控制,防止缓存失效
    var resourceVersion = '20171112'; //版本控制

    //本地SDK方法
    window.mLocalSdk = {//注意相互依赖,需要按顺序加载
    resourceJavascriptList: [
    {
    id:'0',
    url:'./src/js/jquery.js',
    type:'javascript'
    },
    {
    id:'1',
    url:'./src/js/bootstrap.js',
    type:'javascript'
    },
    {
    id:'2',
    url:'./src/js/test.js',
    type:'javascript'
    }
    ],

    resourceCssList : [],
    noNeedUpdate: (function() {
        return localStorage.getItem('resourceVersion') === resourceVersion;
    })(),
    
    isIE: (function(){
        if (!!window.ActiveXObject || "ActiveXObject" in window) //通过能力判断IE
            return true;
        else
            return false;
    })(),
    //判断是否超过localstorage的阀值
    checkHedge: function(){
        var localStorageLength = localStorage.length;
        var localStorageSize = 0;
        for (var i = 0; i < localStorageLength; i++) {
            var key = localStorage.key(i);
            localStorageByte += localStorage.getItem(key).length;
        }
        return localStorageSize;
    },
    
    saveSDK: function() {
        try {
            localStorage.setItem("resourceVersion",resourceVersion);
        } catch (Excepition) {
            if (Exception.name == "QuotaExceededError") {
                localStorage.clear();
                localStorage.setItem("resourceVersion",resourceVersion);
            }
            alert('QuotaExceededError');
        }
    
        for(var i = 0; i< this.resourceJavascriptList.length; i++) {
            var _self = this;//保存this指针
            (function(i){
                var scriptId = _self.resourceJavascriptList[i].id;
                var xhr = new Xhrfactory();
                xhr.get(_self.resourceJavascriptList[i].url,null,function(data){
                    try {
                        localStorage.setItem(scriptId,data);
                    } catch (Exception) {
                        console.log('Excpetion',Excpetion);
                        if (Exception.name == "QuotaExceededError") {
                            localStorage.clear();
                            localStorage.setItem("resourceVersion",resourceVersion);
                        }
                    }
                })
            })(i);
        }
        for(var i = 0; i< this.resourceCssList.length; i++) {
            var _self = this;//保存this指针
            (function(i){
                var cssId = _self.resourceCssList[i].id;
                var xhr = new Xhrfactory();
                xhr.get(_self.resourceCssList[i].url,null,function(data){
                    try {
                        localStorage.setItem(cssId,data);
                    } catch (Exception) {
                        console.log('Excpetion',Excpetion);
                        if (Exception.name == "QuotaExceededError") {
                            localStorage.clear();
                            localStorage.setItem("resourceVersion",resourceVersion);
                        }
                    }
                })
            })(i);
        }
    },
    startup: function(){
        var _self = this;
        if (localStorageSign === 'on' && !this.isIE && window.localStorage) {
            if (this.noNeedUpdate === true) {//使用本地 则在本地进行内联引入
                return (function() {
                    for (var i = 0; i < _self.resourceJavascriptList.length; i++) {
                        var scriptId = _self.resourceJavascriptList[i].id;
                        window.mDomUtils.addJavascriptByInline(scriptId);   
                }
                    for (var i = 0; i < _self.resourceCssList.length; i++) {
                        var cssId = _self.resourceCssList[i].id;
                        var cssString = localStorage.getItem(cssId);
                        window.mDomUtils.addCssByInline(cssString);
                }   
                })();           
            }
            else {
                return (function() {
                    _self.saveSDK(); //这里会存在异步回调问题 需要确保保存后再进行后面的操作 通过open.false解决
                    for (var i = 0; i < _self.resourceJavascriptList.length; i++) {
                        var scriptId = _self.resourceJavascriptList[i].id;
                            window.mDomUtils.addJavascriptByInline(scriptId);   
                    }
                    for (var i = 0; i < _self.resourceCssList.length; i++) {
                        var cssId = _self.resourceCssList[i].id;
                        var cssString = localStorage.getItem(cssId);
                        window.mDomUtils.addCssByInline(cssString);
                    }
                })();
            }
        }
        else {
            return (function() {//不使用本地,则在外链中引入进行下载,这里存在两个异步问题:1.JS没下载完就继续执行其他程序 2.jq和bs无法保证先后依赖顺序下载
                for (var i = 0; i < _self.resourceCssList.length; i++) {
                        window.mDomUtils.addCssByLink(_self.resourceCssList[i]['url']);                 
                }
                window.mDomUtils.addJavascriptByLink(_self.resourceJavascriptList,0);   
            })()
        }
    }
    

    }

    window.mDomUtils = {
    //内联方式 直接写代码
    addJavascriptByInline: function(scriptId) {
    var script = document.createElement('script');
    script.setAttribute('type','text/javascript');
    script.id = scriptId;
    var heads = document.getElementsByTagName('head');
    if(heads.length) {
    heads[0].appendChild(script);
    }
    else {
    document.documentElement.appendChild(script);
    }
    script.innerHTML = localStorage.getItem(scriptId);
    },
    //外链方式 直接引用 需要同步加载js
    addJavascriptByLink: function(list,count) {
    /* var script = document.createElement('script');
    script.setAttribute('type','text/javascript');
    script.setAttribute('src',url);
    script.id = scriptId;
    var heads = document.getElementsByTagName('head');
    if (heads.length) {
    heads[0].appendChild(script);
    } else{
    document.documentElement.appendChild(script);
    }///这种方式会引起js异步加载,无法达到同步效果 不可取
    /
    var xhr = new Xhrfactory();
    xhr.get(url,null,function(data){
    var script = document.createElement('script');
    script.setAttribute('type','text/javascript');
    script.setAttribute('src',url);
    script.id = scriptId;
    var heads = document.getElementsByTagName('head');
    if (heads.length) {
    heads[0].appendChild(script);
    } else{
    document.documentElement.appendChild(script);
    }
    });//这种方式会引起js加载两次 不可取*/
    var head= document.getElementsByTagName('head');
    var script= document.createElement('script');
    script.type= 'text/javascript';
    script.src = list[count].url;
    if (head.length) {
    head[0].appendChild(script);
    } else{
    document.documentElement.appendChild(script);
    }//最终选择这种方式进行递归调用 借用jquery思想
    script.onload = script.onreadystatechange = function() {
    if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete" ) {
    count++;
    if (count < list.length){
    window.mDomUtils.addJavascriptByLink(list,count);
    }
    else {
    return true;
    }
    // Handle memory leak in IE
    script.onload = script.onreadystatechange = null;
    }
    };
    },

    addCssByInline: function(cssString) {
        var link = document.createElement('link');
        link.setAttribute('type','text/css');
        link.setAttribute('rel','stylesheet');
        if(link.stylesheet){
            link.stylesheet.cssText = cssString;
        }
        else {
            var cssText = document.createTextNode(cssString);
            link.appendChild(cssText);
        }
        var heads = document.getElementsByTagName('head');
        if(heads.length) {
            heads[0].appendChild(link);
        }
        else {
            document.documentElement.appendChild(link);
        }
    },
    
    addCssByLink: function(url) {
        var link = document.createElement('link');
        link.setAttribute('href',url);
        link.setAttribute('type','text/css');
        link.setAttribute('rel','stylesheet');
        var heads = document.getElementsByTagName('head');
        if(heads.length) {
            heads[0].appendChild(link);
        }
        else {
            document.documentElement.appendChild(link);
        }
    }
    

    }

    引入方式:

    image.png

    代码地址:

    git clone https://github.com/kingykking/cacheSDK.git

    使用效果:

    使用前:


    image.png

    使用后:


    image.png

    错误记录:

    1.没有按照顺序引入。


    image.png

    2.外链没有按照顺序引入


    image.png
    image.png

    相关文章

      网友评论

          本文标题:利用Localstorage进行JS缓存

          本文链接:https://www.haomeiwen.com/subject/woovmxtx.html