前端性能优化 - 浏览器存储

通常所说的Web缓存指的是可以自动保存常见http请求副本的http设备。对于前端开发者来说,浏览器充当了重要角色。除此外常见的还有各种各样的代理服务器也可以做缓存。当Web请求到达缓存时,缓存从本地副本中提取这个副本内容而不需要经过服务器。

使用缓存有以下优点:

  • 缓存减少了冗余的数据传输,节省流量
  • 缓存缓解了带宽瓶颈问题。不需要更多的带宽就能更快加载页面
  • 缓存缓解了瞬间拥塞,降低了对原始服务器的要求。
  • 缓存降低了距离延时, 因为从较远的地方加载页面会更慢一些。

1. Cookie

某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。

因为http无状态,所以需要cookie去维持客户端的状态,Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用。比如判断用户是否是第一次访问网站,用户是否已经登录等。

1.1 cookie 的处理

  • 服务器像客户端发送cookie
  • 浏览器将cookie保存
  • 之后每次http请求浏览器都会将cookie发送给服务器端

1.2 用途

  • 用于浏览器端和服务器端的交互
  • 客户端自身的数据

1.3 语法

js 通过document.cookie来进行读写操作

// 写入
document.cookie="username=fourteen";

// 您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";

// 您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

// 读取
let cookie = document.cookie;

// 删除
// 删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT: 删除时不必指定 cookie 的值
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

属性:

key-value

max-age: 属性表示缓存时间,单位为秒;

path: 设置该domain下可以访问该Cookie的路径,默认为/

domain: 设置可以访问该Cookie的域名;

httponly: 属性标识一个客户端JavaScript能否操作该cookie;

当用来获取属性值时,document.cookie返回当前页面可用的(根据cookie的域、路径、失效时间和安全设置)所有的字符串,字符串的格式如下:

"name1=value1;name2=value2;name3=value3";

当用来设置值的时候,document.cookie属性可设置为一个新的cookie字符串。这个字符串会被解释并添加到现有的cookie集合中。如:

document.cookie = "_fa=aaaffffasdsf;domain=.dojotoolkit.org;path=/"

设置document.cookie并不会覆盖cookie,除非设置的name value domain path都与一个已存在cookie重复。

由于cookie的读写非常不方便,我们可以自己封装一些函数来处理cookie,主要是针对cookie的添加、修改、删除。

/**
 * cookie操作工具
 */

'use strict';

// 过期时间 12小时
const maxAge = '-1';

export default {
// cookie 设置( escape 用于字符串编码)
    setCookies: cookies => {
        cookies = cookies || {};
        for (let key in cookies) {
            if (!key) continue;
            document.cookie = key + '=' + escape(cookies[key]) + ';expires' + new Date(0).toUTCString() + ';path=/';
        }
    },
    // 根据key获取cookie对应的value
    getCookie: key => {
        let reg = new RegExp('(^| )' + key + '=([^;]*)(;|$)');
        let cookie = document.cookie.match(reg);
        if (cookie) {
            return unescape(cookie[2]);
        } else {
            return null;
        }
    },
    // cookie 中是否含有 keysArr 中所有 key
    hasCookies: keysArr => {
        for (let index in keysArr) {
            var arr; // eslint-disable-line no-unused-vars
            var reg = new RegExp('(^| )' + keysArr[index] + '=([^;]*)(;|$)');
            if (!(arr = document.cookie.match(reg))) return false;
        }
        return true;
    },
    // 清除 cookie 中所有 key
    clearCookies: () => {
        let keys = document.cookie.match(/[^ =;]+(?=\=)/g);
        if (keys) {
            for (let i = 0; i < keys.length; i++) {
                document.cookie = keys[i] + '=0;expires' + new Date(0).toUTCString() + ';path=/';
            }
        }
    }
};

1.4 优势

Cookie的优势是全系列浏览器全部支持,而且可以不传递参数的情况下与后台进行数据交互,最典型的例子就是自动登录。

1.5 限制:

  • 作为浏览器存储,大小4kb左右,
  • IE老版本浏览器会有50个限制,超出会被新的Cooke替换   
  • 需要设置过期时间expire
  • Httponly 不允许js读写
  • Cookie中在相关域名下面 -- cdn的流量损耗,如果域名设置不当,所有请求都会带上Cookie信息,包括图片、css文件等,解决方法:cdn的域名和主站的域名要分开
  • Cookie的读写性能非常非常的差

1.6 优化方案

  1. 去除没有必要的cookie,如果网页不需要cookie就完全禁掉。

  2. 将cookie的大小减到最小。

  3. 由于cookie在访问对应域名下的资源时都会通过HTTP请求发送到服务器,因此,减小cookie的大小,能减小HTTP请求报文的大小,提高响应速度。

  4. 设置合适的过期时间,较长的过期时间可以提高响应速度。给cookie添加一个过期时间,则cookie信息将存储到硬盘上,即使浏览器退出Cookie还会存在。只要Cookie未被清除且还在过期时间内,该Cookie就会在访问对应域名时发送给服务器。

  5. 通过使用不同的domain减少cookie的使用。:cookie在访问对应域名下的资源时都会通过HTTP请求发送到服务器,但在访问一些资源,如js,css和图片时,大多数情况下cookie是多余的,可以使用不同的domain来存储这些静态资源,这样访问这些资源时就不会发送多余的cookie,从而提高响应速度。

 

2. Localstorage

localStorage是H5设计出来专门用于浏览器存储的,提供了快速简单的客户端数据存储功能,可以跨多个会话存储数据,这使得localStorage在世界各地Web开发人员中被广为应用。

为了保持跨浏览器会话,localStorage的数据被写入磁盘中。这意味着当你从localStorage中读取数据时,你实际上是从硬盘驱动器上读取这些字节。读写硬盘开销高昂,特别是相对于读写内存来说。从缓存(对象属性)读取数据和比磁盘(localStorage)读取数据的速度比较快。

localStorage按源存储数据,这意味着,在同一时间内,浏览器中的多个标签页可以访问相同的localStorage数据。

2.1 特点

  • 大小为5M左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封装较好
  • localStorage的关键问题在于它是通过同步操作的方式来进行文件I/o操作。
  • 写入localStorage的数据都会保存到磁盘上,除非主动删除数据,否则数据是永远不会过期的。
  • 用过nodeJs的人都知道,对于文件的I/O是非常昂贵和不一致的(不可信赖)。
  • 任何时间点任何的程序都可以访问文件。举例来说,你注意到过当一个杀毒软件运行的时候你的电脑是如何慢下来的吗?在理想状态下,你读取的文件不会有其他程序在同一时间访问该文件。在极端坏的情况下,如果你想读取一个文件,就必须等待文件上的锁被释放(其他程序操作文件时会锁定文件)。

2.2 问题

localStrorage虽有有永久缓存大量数据的功能,但是要实现这个方案,还需考虑几个问题:

  1. 版本更新机制,项目版本迭代之后,用户仍然从缓存中读取信息
  2. 存在xss安全隐患,毕竟客户端的代码可以任意修改。

2.3 缺点

  1. 兼容性不太好,不支持LS的浏览器比例仍然很大,ie8 ie10不支持;
  2. 静态资源采用LS缓存存在安全隐患;
  3. 非首屏的css可以用LS缓存,首屏如果要考虑SEO,不能使用LS;
  4. 执行速度,读取后使用eval或创建<script>标签的时间会比浏览器直接加载慢。
  5. 版本控制,需要自己写一套版本控制机制。
  6. localStorage以页面的域名划分,而常见的静态资源都以资源本身的域名来缓存,意味着如果你的应用有多个等价域名,它们之间的localStorage不互通,会造成缓存多份浪费。

3. SessionStorage

sessionStorage 属性允许在浏览器中存储 key/value 对的数据。用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。

  • 会话级别的浏览器缓存
  • 大小5M左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封装较好
  • 对于表单信息的维护

4. IndexDB

indexDB是一种低级API,用于客户端存储大量结构化数据。该API使用索引来实现对该数据的高性能搜索。虽然Web Storage对于存储较少量的数据很有用,但是对于存储更大量的结构化数据来说,这种方法不太有用,IndexDB提供了一个解决方案

为应用创建离线版本

 

5. Service workers

5.1 产生意义

Js单线程,在请求大规模数据和运算的时候,会阻塞后面的进行,比如3D模型数据

5.2 PWA Progressive Web Apps

是一种web App 新模型,并不是指某一种前沿的技术或者某一单一的知识点,是一种渐进式的web app,是通过一系列的web特性,配合优秀个UI交互设计,逐步增强webapp的用户体验

  • 可靠: 在没有网络的环境中也能提供基本的页面访问,而不会出现未连接到互联网的页面

  • 快速: 针对网页渲染及网络数据访问有较好的优化

  • 融入: 应用可以被增加到手机桌面,并且和普通应用一样有全屏、推送等特性

5.3 Service workers

一个脚本,浏览器独立于当前网页,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开了一扇大门。在未来这些特性将包括推送信息,背景后台同步,geofencing地理围栏定位),但他将推出的第一个首要特性,就是拦截和处理网络请求的能力,包括编程方式来管理被缓存的相应。

  1. 使用拦截和处理网络请求的能力,去实现一个离线应用
  2. 使用service worker在后台运行同时能和页面通信的能力,去实现大规模后台数据的处理,不阻塞主线程

5.4 生命周期

Chrome 对service 的检查

chrome://serviceworker-internals/

chrome://inspect/#service-workers

let request = window.indexedDB.open('test');
console.log(request);

et myDB = {
    name: 'test',
    version: '1.0.0',
    db: null
};
let openDB = (name, callback) => {
    // 建立打开indexDB
    let request = window.indexedDB.open(name);
    request.onerror = (e) => {
        window.document.write('open indexDB error');
    };

    request.onsuccess = (e) => {
        myDB.db = e.target.result;
        callback && callback()
    }
};
openDB(myDB.name, (e) => {
    // 关闭indexDB
    myDB.db.close();

    // 删除indexDB
    window.indexedDB.deleteDatabase(myDB.db);
});

indexDB基础操作

let myDB = {
    name: 'test10',
    version: '10',
    db: null
};
let openDB = (name, callback) => {
    // 建立打开indexDB
    let request = window.indexedDB.open(name);
    request.onerror = (e) => {
        window.document.write('open indexDB error');
    };

    request.onsuccess = (e) => {
        myDB.db = e.target.result;
        callback && callback();
    };

    request.onupgradeneeded = () => {
        let store = myDB.db.createObjectStore('books', {
            keyPath: 'isbn'
        });

        let titleIndex = store.createIndex('by_title', 'title', {
            unique: true
        });

        let authorIndex = store.createIndex('by_author', 'author');

        store.put({
            title: 'title',
            author: 'author',
            isbn: 123456
        });

        store.put({
            title: 'title1',
            author: 'author1',
            isbn: 12345
        });

        store.put({
            title: 'title2',
            author: 'author2',
            isbn: 1234
        })
    }
};

let addData = (db, storeName) => {
    // object store

};

openDB(myDB.name, (e) => {
    // 关闭indexDB
    // myDB.db.close();
    //
    // // 删除indexDB
    // window.indexedDB.deleteDatabase(myDB.db);
});

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值