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

原理如下:

一次批量加要加载的文件存入数组,采用Ajax方式异步载入各个文件,然后采用循环方式逐个执行下载下来的Js或者Css文件,如果已经被缓存(localStorage)的则省略下载过程。

由于JS采用的是单线程模式运行,在执行某一个js时会阻塞其它并发的js执行,所以会按顺序执行各个js。在执行完所有的脚本之后,图片会被浏览器接着 加载,所以第一次加载速度略慢,后面就会比较快了。在JQuery Mobile 1.4.5+FireFox/微信浏览器下实测效果不错,IE就被省略了,我主要是要在微信浏览器下使用。

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

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

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

//用于获取的脚本或css文件保存对象
function HttpGetObject() {
    this.url = null;        //要下载的文件路径
    this.cache_key = null;  //缓存键
    this.chunnel = null;    //通道名
    this.type = null;       //类型,js或css
    this.is_fill = false;   //内容是否被填充
    this.is_exec = false;   //内容是否已被执行,防止分几大块载入后重复执行
}

//通信处理类,可以静态引用其中的方法
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,即异步处理
    * @param _paraObj:相关的参数对象
    */
    this.send = function (_url, _data, _processRequest, _chunnel, _asynchronous, _paraObj) {
        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, _paraObj);
                    }
                    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, _paraObj);
        }
    }
}

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

    //获取env.js文件所在路径
    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();

    //获取文件后缀名
    this.getFileExt = function (fileUrl) {
        var d = /\.[^\.]+$/.exec(fileUrl);
        return d.toString().toLowerCase();
    }

    //依次放入要载入的文件
    this.pushNeedLoad = function (url) {
        var _absUrl = null;
        if (url.charAt(0) == ‘/‘)
            _absUrl = url;
        else
            _absUrl = this.envPath + url;

        var object = new HttpGetObject();
        object.url = _absUrl;
        object.cache_key = envLastVer + _absUrl;    //利用版本号+绝对路径生成缓存键
        object.chunnel = ‘ch‘ + (this.needLoadObject.length + 1);
        object.type = this.getFileExt(_absUrl);

        //尝试从缓存获取
        var cacheContent = localStorage.getItem(object.cache_key);
        if (cacheContent) { object.is_fill = true; }

        this.needLoadObject.push(object);
        return this;
    }

    //依次装载要处理的文件
    this.batchLoad = function () {
        for (var i = 0; i < this.needLoadObject.length; i++) {
            var item = this.needLoadObject[i];
            var processGet = function (_instance, _paraObj) {
                localStorage.setItem(_paraObj.cache_key, _instance.responseText);    //缓存文件
                _paraObj.is_fill = true;
            }
            if (item.is_fill == false) {
                Request.send(item.url, "", processGet, item.chunnel, false, item);  //采用同步方式载入
            }
        }
        return this;
    }

    //依次执行要处理的文件
    this.batchExec = function () {
        var runCss = function (_css) { document.write(‘<style type="text/css">‘ + _css + ‘</style>‘); }
        var runJs = function (_js) {
            if (window.execScript)
                window.execScript(_js);
            else
                window.eval(_js);
        }
        //依次执行,由于js为单线程执行,每执行一个js都会阻塞其它,所以可以保证顺序执行
        for (var i = 0; i < this.needLoadObject.length; i++) {
            var item = this.needLoadObject[i];
            if (item.is_exec == false) {
                if (item.type == ‘.js‘) {
                    runJs(localStorage.getItem(item.cache_key));
                    item.is_exec = true;  //标记已执行,下次不会再执行
                }
                else if (item.type == ‘.css‘) {
                    runCss(localStorage.getItem(item.cache_key));
                    item.is_exec = true;  //标记已执行,下次不会再执行
                }
            }
        }
    }
}

调用方法

Env.pushNeedLoad("jquery.mobile-1.4.5/jquery.min.js")
            .pushNeedLoad("jquery.mobile-1.4.5/jquery.mobile-1.4.5.min.css")
            .pushNeedLoad("/plus_in/weixin/procedure/scripts/task.util.js")
            .pushNeedLoad("/plus_in/weixin/procedure/scripts/emcp.mobile.js")
            .pushNeedLoad("/plus_in/weixin/procedure/scripts/common.index.js")
            .pushNeedLoad("jquery.mobile-1.4.5/jquery.mobile-1.4.5.min.js")
            .pushNeedLoad("mobiscroll.2.6/css/mobiscroll.custom-2.6.2.min.css")
            .pushNeedLoad("mobiscroll.2.6/js/mobiscroll.custom-2.6.2.min.js")
            .pushNeedLoad("/plus_in/weixin/procedure/style/base.css")
            .batchLoad().batchExec();

引用:http://www.cnblogs.com/wubin264/p/load_js_css_into_localstorage.html

时间: 2024-10-22 10:56:54

将js和css文件装入localStorage加速程序执行的相关文章

Web移动端使用localStorage缓存Js和CSS文件

将js css文件缓存到localstorage区可以减少页面在加载时与HTTP请求的交互次数,从而优化页面的加载时间. 电脑端使用localstorage是测试没有问题的,但是用android的apk打包之后,导致localstorage失效,无法进行缓存,查阅资料之后,得知解决方法: 安卓代码: mWebView.getSettings().setDomStorageEnabled(true); mWebView.getSettings().setAppCacheMaxSize(1024*1

后台修改js或者css文件之后,客户端刷新但是无效的问题

前端开发会遇到一个问题:修改测试前端代码的时候,有时候修改了css或者js文件,但是前端刷新的时候却没有反应,不免让人感觉是不是修改错误,其实这有可能是客户端缓存问题.解决方法: 1)Ctrl+F5,清除浏览器缓存(等同于浏览器-->历史数据-->删除cookies) 2)在js或css后加版本号,这时候浏览器客户端会认为这是不同版本的js或者css文件,会自动重新刷新下载(浏览器会缓存下载页面js和css文件) 2.1)形如:.css?v=x  或者 css?version=x     &l

2个方法通过字[符串参数]加载外部js和css文件

Java语言的异常处理机制可以去确保程序的健壮性,提高系统的可用率,但是Java API提供的异常都是比较低级的(这里的低级是指 " 低级别的 " 异常),只有开发人员才能看的懂,才明白发生了什么问题.而对于终端用户来说,这些异常基本上就是天书,与业务无关,是纯计算机语言的描述,那该怎么办?这就需要我们对异常进行封装了. 近年来,深度学习的研究越来越深入,在各个领域也都获得了不少突破性的进展.基于注意力(attention)机制的神经网络成为了最近神经网络研究的一个热点,本人最近也学习

gulp-rev同时将js和css文件写在一个rev-manifest.json文件里面的方式探讨

参考: https://segmentfault.com/q/1010000002876613 https://github.com/sindresorhus/gulp-rev 测试发现,在官网上最主要的做法是: 加入如下参数: { base: 'build/assets', merge: true } 其中base为存放上一个生成的rev-manifest.json文件,然后merge为是否拼合进去,最后再输出到base这个目录上,就可以实现js和css文件同在一个rev-manifest.j

引入JS和CSS文件加版本号的作用

形如: <script type="text/javascript" src="/resources/js/myFunction.js?version=0.1.0"></script> <link rel="stylesheet" type="text/css" href="/resources/css/styles/myLocation.css?version=0.1.0"

Django中载入js和css文件

Django中载入js和css文件 项目的文件夹结构例如以下: mysite |-mysite |-|-static |-|---js和css文件 |-|-|-init.py |-| |-models.py |-| |-views.py |-|-init.py |-|-settings.py |-|-urls.py |-templates |-|-(template html 文件) settings.py中static变量的设置: STATIC_ROOT = os.path.join(os.p

动态添加div及对应的js、css文件

动态添加div及对应的js.css文件 在近期的项目开发中需要在首页中添加很多面板型的div,直接加载代码显得很繁琐,于是利用js封装一个动态添加div及其对应css文件和js文件的方法供大家参考使用. /*利用Jquer动态加载div及对应的CSS文件.js文件.好处减少Index页面中代码的冗余,方便维护*/ /** *config参数说明: var config = { name: 'demo2', ***需要添加的div的html文件名称 divContainer: 'div2',***

Django中加载js和css文件

Django中加载js和css文件 项目的目录结构如下: mysite |-mysite |-|-static |-|---js和css文件 |-|-|-init.py |-| |-models.py |-| |-views.py |-|-init.py |-|-settings.py |-|-urls.py |-templates |-|-(template html 文件) settings.py中static变量的设置: STATIC_ROOT = os.path.join(os.path

使用Maven构建Java Web项目时,关于jsp中引入js、css文件路径问题。

今天有点闲,自己动手搭建一个Java Web项目,遇到jsp中引入js.css文件时路径不正确的问题,于是在网上查阅了很多资料,最终都无法解决问题,于是,上stackoverflow找到了解决方法,这里不得不吐槽一下国内资料的可信度,不说了,以后遇到问题尽量还是google吧,花点钱买个vpn值了,生命有限,节约时间. 下面记录下解决方法吧: 首先,确保jsp引入了jstl:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" pr