将js和css文件装入localStorage加速程序执行

首先感谢某某作者写的文章:http://www.jb51.net/article/12793.htm

直接上代码,注意文件名为env.js

//需要引用别的js的时候,就加上如Env.require("cookie.js"),或Env.require("/common/cookie.js"),是用相对路径还是绝对路径就看喜好了。
//Env.require可用在页面模板中,也可用在js文件中,但一定要保证执行时env.js被显式引入。
//多次Env.require同一个js(不管用相对还是绝对),只有第一次会加载,所以不会重复。

//程序最后发行的版本,用于作为缓存键的前缀,快速更新缓存
var envLastVer = ‘2014_11_15_13_47‘;

//用于存放通道名称及通信对象的类,这样可以通过不同通道名称来区分不同的通信对象  
function HttpRequestObject() {
    this.chunnel = null;
    this.instance = null;
}

//通信处理类,可以静态引用其中的方法  
var Request = new function () {

    //通信类的缓存  
    this.httpRequestCache = new Array();

    //创建新的通信对象 
    this.createInstance = function () {
        var instance = null;
        if (window.XMLHttpRequest) {
            //mozilla  
            instance = new XMLHttpRequest();
            //有些版本的Mozilla浏览器处理服务器返回的未包含XML mime-type头部信息的内容时会出错。
            //因此,要确保返回的内容包含text/xml信息  
            if (instance.overrideMimeType) {
                instance.overrideMimeType = "text/xml";
            }
        }
        else if (window.ActiveXObject) {
            //IE  
            var MSXML = [‘MSXML2.XMLHTTP.5.0‘, ‘Microsoft.XMLHTTP‘, ‘MSXML2.XMLHTTP.4.0‘, ‘MSXML2.XMLHTTP.3.0‘, ‘MSXML2.XMLHTTP‘];
            for (var i = 0; i < MSXML.length; i++) {
                try {
                    instance = new ActiveXObject(MSXML[i]);
                    break;
                }
                catch (e) {
                }
            }
        }
        return instance;
    }

    /**  
    * 获取一个通信对象  
    * 若没指定通道名称,则默认通道名为"default"  
    * 若缓存中不存在需要的通信类,则创建一个,同时放入通信类缓存中  
    * @param _chunnel:通道名称,若不存在此参数,则默认为"default"  
    * @return 一个通信对象,其存放于通信类缓存中  
    */
    this.getInstance = function (_chunnel) {
        var instance = null;
        var object = null;
        if (_chunnel == undefined)//没指定通道名称  
        {
            _chunnel = "default";
        }
        var getOne = false;
        for (var i = 0; i < this.httpRequestCache; i++) {
            object = HttpRequestObject(this.httpRequestCache[i]);
            if (object.chunnel == _chunnel) {
                if (object.instance.readyState == 0 || object.instance.readyState == 4) {
                    instance = object.instance;
                }
                getOne = true;
                break;
            }
        }
        if (!getOne) //对象不在缓存中,则创建  
        {
            object = new HttpRequestObject();
            object.chunnel = _chunnel;
            object.instance = this.createInstance();
            this.httpRequestCache.push(object);
            instance = object.instance;
        }
        return instance;
    }

    /**  
    * 客户端向服务端发送请求  
    * @param _url:请求目的  
    * @param _data:要发送的数据  
    * @param _processRequest:用于处理返回结果的函数,其定义可以在别的地方,需要有一个参数,即要处理的通信对象  
    * @param _chunnel:通道名称,默认为"default"  
    * @param _asynchronous:是否异步处理,默认为true,即异步处理  
    */
    this.send = function (_url, _data, _processRequest, _chunnel, _asynchronous) {
        if (_url.length == 0 || _url.indexOf("?") == 0) {
            alert("由于目的为空,请求失败,请检查!");
            return;
        }
        if (_chunnel == undefined || _chunnel == "") {
            _chunnel = "default";
        }
        if (_asynchronous == undefined) {
            _asynchronous = true;
        }
        var instance = this.getInstance(_chunnel);
        if (instance == null) {
            alert("浏览器不支持ajax,请检查!")
            return;
        }
        if (_asynchronous == true && typeof (_processRequest) == "function") {
            instance.onreadystatechange = function () {
                if (instance.readyState == 4) // 判断对象状态  
                {
                    if (instance.status == 200) // 信息已经成功返回,开始处理信息  
                    {
                        _processRequest(instance);
                    }
                    else {
                        alert("您所请求的页面有异常,请检查!");
                    }
                }
            }
        }
        //_url加一个时刻改变的参数,防止由于被浏览器缓存后同样的请求不向服务器发送请求  
        if (_url.indexOf("?") != -1) {
            _url += "&requestTime=" + (new Date()).getTime();
        }
        else {
            _url += "?requestTime=" + (new Date()).getTime();
        }
        if (_data.length == 0) {
            instance.open("GET", _url, _asynchronous);
            instance.send(null);
        }
        else {
            instance.open("POST", _url, _asynchronous);
            instance.setRequestHeader("Content-Length", _data.length);
            instance.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            instance.send(_data);
        }
        if (_asynchronous == false && typeof (_processRequest) == "function") {
            _processRequest(instance);
        }
    }
}

var Env = new function () {
    this.funcList = new Array();
    this.cssList = new Array();

    this.envPath = null;

    this.getPath = function () {
        this.envPath = document.location.pathname;
        this.envPath = this.envPath.substring(0, this.envPath.lastIndexOf("/") + 1);
        var _scripts = document.getElementsByTagName("script");
        var _envPath = null;
        var _scriptSrc = null;
        for (var i = 0; i < _scripts.length; i++) {
            _scriptSrc = _scripts[i].getAttribute("src");
            if (_scriptSrc && _scriptSrc.indexOf("env.js") != -1) {
                break;
            }
        }
        if (_scriptSrc != null) {
            if (_scriptSrc.charAt(0) == ‘/‘) {
                this.envPath = _scriptSrc.substr(0, _scriptSrc.length - 6);
            }
            else {
                this.envPath = this.envPath + _scriptSrc.substr(0, _scriptSrc.length - 6);
            }
        }
    }
    this.getPath();

    //执行返回的脚本内容,_language可以为空,默认为JavaScript
    this.runScript = function (_script, _language) {
        //为兼容firefox做判断  
        if (_language != undefined) {
            if (window.execScript)
                window.execScript(_script, _language);
            else
                window.eval(_script, _language);
        }
        else {
            if (window.execScript)
                window.execScript(_script);
            else
                window.eval(_script);
        }
    }

    /**  
    * 按需获取需要的js文件
    * @param _cacheKey:缓存键,全局唯一
    * @param _jsName:js文件路径,若为相对路径,则是对应env.js的相对路径,也可以用绝对路径  
    * @param _language:对返回函数进行处理的语言,默认为JScript,可不填  
    */
    this.requireJs = function (_cacheKey, _jsName, _language) {
        var _absJsName = null;
        if (_jsName.charAt(0) == ‘/‘)
            _absJsName = _jsName;
        else
            _absJsName = this.envPath + _jsName;
        if (!Env.funcList[_absJsName]) {
            Env.funcList[_absJsName] = "finished";
            var processJs = function (_instance) {
                localStorage.setItem(envLastVer + _cacheKey, _instance.responseText);    //缓存文件
                this.runScript(_instance.responseText, _language);   //运行文件
            }
            if (_cacheKey) {
                var cacheFile = localStorage.getItem(envLastVer + _cacheKey);
                if (cacheFile) { this.runScript(cacheFile); }
                else {
                    Request.send(_absJsName, "", processJs, "", false);
                }
            } else {
                Request.send(_absJsName, "", processJs, "", false);
            }
        }
    }

    //在页面上载入css
    this.runCss = function (_css) { document.write(‘<style type="text/css">‘ + _css + ‘</style>‘); }

    //按需获取需要的css文件
    //优点:支持缓存、图片路径不用重新计算
    this.requireCss = function (_cacheKey, _cssName) {
        var _absCssName = null;
        if (_cssName.charAt(0) == ‘/‘)
            _absCssName = _cssName;
        else
            _absCssName = this.envPath + _cssName;
        var processCss = function (_instance) {
            localStorage.setItem(envLastVer + _cacheKey, _instance.responseText);
            this.runCss(_instance.responseText);
        }
        if (_cacheKey) {
            var cacheFile = localStorage.getItem(envLastVer + _cacheKey);
            if (cacheFile) { this.runCss(cacheFile); }
            else {
                Request.send(_absCssName, "", processCss, "", false);
            }
        } else {
            Request.send(_absCssName, "", processCss, "", false);
        }
    }
}

 下面是调用方法:

        Env.requireJs(‘jquery1.10.2‘, "jquery.mobile-1.4.5/jquery.min.js");
        Env.requireCss(‘jquerymobile1.4.5css‘, "jquery.mobile-1.4.5/jquery.mobile-1.4.5.min.css");
        Env.requireJs(‘jquerymobile1.4.5‘, "jquery.mobile-1.4.5/jquery.mobile-1.4.5.min.js");
        Env.requireCss(‘mobiscroll.custom-2.6.2.min.css‘, "mobiscroll.2.6/css/mobiscroll.custom-2.6.2.min.css");
        Env.requireJs(‘mobiscroll.custom-2.6.2.min.js‘, "mobiscroll.2.6/js/mobiscroll.custom-2.6.2.min.js");

通过火狐F12观察,发现上面的脚本第一次会被加载,后面将会直接从localstorage中读取,节省了很多,将js用于微信浏览器后,也节省了很多带宽。不过第一次加载还是有些慢的,毕竟还是有那么多数据。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。