前端性能优化——通用的本地缓存SDK

版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接 https://blog.csdn.net/qq_40109752/article/details/83009811

说明:该文章自编,学习成果来源于 @慕课cc老师。代码是参考之后,自己实战编码的,对 @慕课cc老师的代码有相应更改如有不当,马上删除。非常感谢!

优点

  1. 缩短用户进入页面的时间
  2. 使用本地储存的资源减少网络请求,减小网络压力
  3. 重要资源存放在本地加快页面对用户的相应

存储方案选取

  1. SessionStorage

    临时存储神器,关闭页面标签自动回收,不可以跨页面交互。

  2. userData 是为ie服务的

    优点:第一个吃螃蟹的人,也得感谢第一个被吃的螃蟹

    缺点:存储限制大小,单个文件的大小限制是128K,一个域名下总共可以保存1024KB的文件,文件个数应该没有限制。在受限站点里这两个值分别是64K和640KB.

  3. Cookie 兼容性最好的本地存储

    优点:兼容性最好,几乎所有浏览器都支持

    缺点:大小有限制,而且每次发送请求,请求头里会带着Cookie一起发过去,现在大多数登录的合法性验证都是用cookie验证的。

  4. openDatabase 没有他做不了的,但是对数据库知识有要求

    优点:就是一个完成的数据库

    缺点:可能对于前端来说,成本高

  5. localstorage

    优点:兼容性中等,操作简单,就是key-value形似,几乎现代的浏览器都支持。

    缺点:存在大小限制,IE9、IE10不支持

    注意:不同浏览器读取不到数据(先是用的火狐浏览器,后来换成谷歌浏览器,是读取不到数据的);不同浏览器的存储大小是不一样的,就是一个界值。

思路(如图)

  1. 缓存对象 —— 储存优先加载的模块,且其优先级非常高

  2. 需要一个接口判断需不需要拉取新的资源,是否开启本地缓存的标识,资源列表

    标识:LOCALSTORAGESIGN 、 版本号:RESOURCEVERSION、  资源:RESOURCELIST
    
  3. 如图
    本地缓存SDK 思路图

代码

  1. index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>本地SDK缓存测试</title>
</head>
<body>
<div id="wrap">
</div>
<script src="../script/localSdk.js"></script>
<script>
    // 当前定义的全局的 变量菊娥可来自服务器
    // 当前的资源版本
    const RESOURCEVERSION = '114534324';
    // 当前是否启动本地的localStorage存储
    const LOCALSTORAGESIGN = "on";
    // 当前管理的资源列表
    const RESOURCELIST = [
        {
            id : "101",
            url :"../script/getName.js",
            type : 'js'
        },
        {
            id : "102",
            url : '../script/sayName.js',
            type : 'js'
        },
        {
            id : "201",
            url : '../style/index.css',
            type : 'css'
        }
    ]

    localSdk(RESOURCEVERSION, LOCALSTORAGESIGN, RESOURCELIST);
</script>
</body>
</html>
  1. localSdk.js
/**
 * @author NZQ
 * @data 2018/10/10
 * @Description : 本地通用缓存
 */

window.localSdk =  function (resourceVersion, localStorageSign, resourceList) {
    // XHR
    function Xhrfactory () {
        this.init.apply(this, arguments);
    }
    Xhrfactory.prototype = {
        // 初始化
        init : function () {
            this.xhr = this.create();
        },
        // 创建xhr
        create : function () {
            let xhr = null;
            if (window.XMLHttpRequest) {
                xhr = new XMLHttpRequest();
            }else {
                xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }

            return xhr;
        },
        // 回调函数
        readyState : function (callback) {
            this.xhr.onreadystatechange = function () {
                if (this.readyState === 4 && this.status === 200) {
                    callback(this.responseText);
                }
            }
        },
        // 参数装换
        para : function (data) {
            let datastr = '';
            if (data && Object.prototype.toString.call(data) === "[object Object]") {
                for (let key in data) {
                    datastr += key + "=" + data.key;
                }
            }
            return datastr;
        },
        // 请求发送
        get : function (url, data, callback) {
            // 这里先写这个函数的原因是 将xhr状态改变是的回调函数提前, 防止请求完成、状态改变,但是没有为相应的事件赋上处理函数
            this.readyState(callback);
            let newurl = url + "?" + this.para(data);
            this.xhr.open('get', newurl, true);
            this.xhr.send(null);
        }
    }

    // SDK
    let mLocalSdk = {
        // 判断是否需要更新缓存
        needUpdate : (function () {
            // 与本地缓存的一致 就 不需要缓存
            return !(localStorage.resourceVersion === resourceVersion);
        })(),
        // 判断是否是IE浏览器
        isIE : (function () {
            // ie的最低版本 4
            let v = 3;
            let div = document.createElement('div');
            let all = div.getElementsByTagName('i');
            while(
                // !all[0] 没有加进去 为 正确
                div.innerHTML = '<!-- [if gt IE' + (++v) + ']><i></i><![endif] -->', !all[0]
                ){ if (v > 11) { return false }  }
            return v > 3 ? v : false;
        })(),
        // 判断当前状态下是否 localStorage 溢出
        checkHedge : function () {
            let localStorageLength = localStorage.length;
            let localStorageSize = 0;
            for (let i = 0; i < localStorageLength; i++) {
                let key = localStorage.key(i);
                localStorageSize += localStorage.getItem(key).length
            }

            return localStorageSize;
        },
        // 启动方法, 读取本地的缓存
        startUp : function () {
            // 能使用本地缓存
            if (localStorageSign === 'on' && !this.isIE && window.localStorage) {
                // 不需要更新
                if (!this.needUpdate) {
                    console.log('可缓存,且不需要更新');
                    for (let i = 0,length = resourceList.length; i < length ; i++ ) {
                        let id = resourceList[i].id;
                        let type = resourceList[i].type
                        // 相应的插入操作
                        if (type === 'js') {
                            mDomUtils.addJsByLocalStorage(id);
                        } else if (type === 'css') {
                            mDomUtils.addCssByLocalStorage(id)
                        }
                    }
                }
                // 需要更新
                else{
                    console.log('可缓存,且需要更新');
                    this.saveSdk();
                    for (let i = 0,length = resourceList.length; i > length ; i++ ) {
                        let id = resourceList[i].id;
                        let type = resourceList[i].type

                        // 相应的插入操作
                        if (type === 'js') {
                            mDomUtils.addJsByLocalStorage(id);
                        } else if (type === 'css') {
                            mDomUtils.addCssByLocalStorage(id)
                        }
                    }
                }
            }
            // 不能使用本地缓存
            else {
                console.log('不可缓存,link方法');
                // 不能使用本地缓存时
                for (let i = 0, lngth = resourceList.length; i < length; i++) {
                    let url = resourceList[i].url;
                    let type = resourceList[i].type
                    // 相应的插入操作
                    if (type === 'js') {
                        mDomUtils.addJsByLink(url);
                    } else if (type === 'css') {
                        mDomUtils.addCssByLink(url)
                    }
                }
            }
        },
        // 版本 和 请求到的资源 保存到本地缓存
        saveSdk : function () {
            // 版本相关
            try {
                localStorage.setItem('resourceVersion', resourceVersion);
            } catch (oException) {
                // 此时localStorage 已满
                if (oException === 'QuotaExceededError') {
                    localStorage.clear();
                    localStorage.setItem('resourceVersion', resourceVersion);
                }
            }

            // 资源 相关
            for (let i = 0, length = resourceList.length; i < length; i++) {
                let id = resourceList[i].id;
                let xhr = new Xhrfactory();
                xhr.get(resourceList[i].url, null, function (data) {
                    try {
                        localStorage.setItem(id, data);
                    } catch (oException) {
                        if (oException === 'QuotaExceededError') {
                            localStorage.clear();
                            localStorage.setItem(id, data)
                        }
                    }
                })
            }
        }
    }

    // DOM 操作相关
    let mDomUtils = {
        // 通过本地储存添加js
        addJsByLocalStorage : function (scriptId) {
            let script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            let heads = document.getElementsByTagName('head');
            if (heads.length) {
                heads[0].appendChild(script);
            } else {
                document.documentElement.appendChild(script);
            }
            script.innerHTML = localStorage.getItem(scriptId);
        },
        // 通过链接 添加js
        addJsByLink : function (jsUrl) {
            let script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            script.setAttribute('src', jsUrl);
            let heads = document.getElementsByTagName('head');
            if (heads.length) {
                heads[0].appendChild(script);
            } else {
                document.documentElement.appendChild(script);
            }
        },
        // 通过本地储存添加css
        addCssByLocalStorage : function (cssId) {
            let doc = document;
            let cssString = localStorage.getItem(cssId);
            let style = doc.createElement('style');
            style.setAttribute('type', 'text/css');
            if (style.stylesheet) {
                // IE支持
                style.stylesheet.cssText = cssString;
            } else {
                // w3c
                let cssText = doc.createTextNode(cssString);
                style.appendChild(cssText);
            }

            let heads = doc.getElementsByTagName('head');
            if (heads.length) {
                heads[0].appendChild(style);
            } else {
                doc.documentElement.appendChild(style);
            }
        },
        // 通过链接 添加css
        addCssByLink : function (cssUrl) {
            let doc = document;
            let link = doc.createElement('link');
            link.setAttribute('type', 'text/css');
            link.setAttribute('rel', 'stylesheet');
            link.setAttribute('href', cssUrl);
            let heads = doc.getElementsByTagName('head');
            if (heads.length) {
                heads[0].appendChild(link);
            } else {
                doc.documentElement.appendChild(link);
            }
        }
    }

    mLocalSdk.startUp();
}
  1. index.css
#wrap {
    width: 100px;
    height: 100px;
    margin: 0 auto;
    background-color: red;
}
  1. getName.js
/**
 * @author NZQ
 * @data 2018/10/10
 * @Description :
 */

function getName () {
    return {
        name : "nzq"
    }
}
  1. sayName.js
/**
 * @author NZQ
 * @data 2018/10/10
 * @Description :
 */

(
    function () {
        alert(getName().name)
    }
)();

猜你喜欢

转载自blog.csdn.net/qq_40109752/article/details/83009811