本文禁止转载,由UC浏览器内部出品。

0.前言

大纲

浏览器缓存和存储相关的功能分为四类:

  1. 加载流程

    • Memory Cache
    • Application Cache(简称AppCache)
    • HTTP Cache
    • Cookie Storage
  2. Javascript API
    • Web Storage
    • Indexed Database
    • File API
    • Cache Storage(Service Worker的核心功能)
    • Filesystem API
    • Quota Management API
  3. 前进后退
    • Page Cache(Back-Forward Cache)
    • History
  4. 保存网页

术语表

英文 中文意思 解释
Resource 资源 所有的网络文件都称为资源,HTML文档、CSS、javascript、图片等
Loader 加载器 浏览器中负责加载资源的模块
net module/library 网络库 负责网络IO的模块,可简单理解为HTTP协议的实现者
Layout Engine 排版引擎 负责HTML解析和加载控制的模块,在WebKit时期,它被称为渲染引擎Render Engine

1. Cache综述

浏览器排版引擎中负责加载资源流程的模块,我们称之为Loader。在Chromium中,Loader被更细化为负责控制由HTML标准(包括HTML标签和Javascript)发起的各种资源加载过程,实际的网络IO由专门的网络模块负责,而在网络模块和Loader之间还有一层叫做fetch。fetch仍属于排版引擎,和网络模块之间是隔开层次的。对前端来说仅需知道fetch里面包含Memory Cache作为第一级缓存。Loader是依次按不同条件从Memory Cache、AppCache、HTTP Cache里获取已缓存的资源的,拿不到才会去下一种Cache里找。

// javascript伪码描述的加载过程
function loadResource(request) {
  CookieStorage.addCookieIfMatch(request);
  if (MemoryCache.containsValidCache(request)) {
    return MemoryCache.fetch(request);
  } else if (request.isFromAppCache) {
    if (AppCache.containsValidCache(request)) {
      return AppCache.fetch(request);
    } else {
      return AppCache.loadFromNetworkThenStore(request);
    }
  } else if (HttpCache.containsValidCache(request)) {
    return HttpCache.fetch(request);
  } else {
    return NetworkTransaction.fetch(request);
  }
}

其中,Memory Cache缓存的数据是始终保存在内存中的,AppCache和HTTP Cache都是在磁盘中。这个设计就是模仿CPU-内存-磁盘外存这三者。

磁盘属于外部设备,CPU不能直接访问硬盘上的数据,要先将硬盘上的数据读取到内存,然后CPU访问内存上的数据。Loader和CPU一样,无论是从网络还是从磁盘缓存加载,得到的数据都先组织好放在内存再继续其它操作。后续如果还要操作这些资源,就可能是直接访问内存中的备份,以达到极高的性能。

HTTP Cache如其名,属于HTTP(S)协议的数据流缓存,是排版引擎外的网络模块的一部分,数据存于磁盘。AppCache和HTTP Cache在磁盘缓存这部分的实现是一样的,只是根据规范而有不同的进出条件。从规范也可知,优先判断是否走AppCache。

下面是Cache中的数据流:



(不好意思,图懒得搞得好看些)

从图中可以看到,Memory Cache会连同解码后的数据一同缓存,所以特别地快。

由于AppCache是由HTML标签里的manifest属性来操控的,属主动行为,所以暂不在Cache这一章中叙述。

无论哪种Cache,都是以URL为key做映射关系来判断是否缓存有响应数据。

在隐身窗口,Chromium是不会把任何资源写入磁盘的,所有的信息都放在内存中。但是其它浏览器,为了追求一定的用户体验,会使用HTTP Cache来存取部分资源。这就要求有一定的算法,既能保护隐私又能复用缓存。

2 Memory Cache

综述

Memory Cache不是任何规范要求这么做的,是浏览器的优化,但为了实现规范又自然而然需要这么做。因为浏览器窗口随时可能需要重绘,例如改变窗口大小、改变滚动条位置或JS修改DOM等,那么当前网页的所有资源都必须保留在内存中才能迅速响应,也就是不跳出当前网页,其所有资源都需要缓存在内存中。把这种缓存按一定算法在超出需要的时期仍保留,就成了Memory Cache。

因为Memory Cache仍属于排版引擎,数据可以被Loader直接使用,所以是最高效的Cache。根据HTTP协议,如果资源被设置成很快过期,那么过期以后即使Memory Cache存有备份,还是会向下一级Cache索取资源的。

除了过期,缓存是否可用还有一些条件,例如:method和body相同、安全政策相同(允许使用Cookie或凭证与否)、大部分的Header相同等。还有其它一些考虑,不一一列出了,但基本都有相关的规范来描述,且随着HTML5功能的增加还在扩充中。稍微一提是,如果这个资源Revalidation后仍可用(HTTP GET 304),也还是用内存的缓存,不是先淘汰再从磁盘拿。

Chromium的代码参考:

RawResource::canReuse()


ResourceFetcher::determineRevalidationPolicy()

内容

缓存的是原始数据和解码后数据。其中文本经过了UTF-8解码,图片会被解码成RGBA序列。

容量

Memory Cache的实现中有个重要的概念:当前页面用到的资源称为活动资源,离开当前页面后,在新页面没用到的资源都变成非活动资源。Memory Cache是对非活动资源是有限制的,容量为8MB,这包括原始数据和解码后的数据。对活动资源则无任何限制,并不会说不可见就释放掉。所以普通的无限滚动网页迟早会用尽内存,导致浏览器卡顿甚至crash。前端需要做的一个改进就是动态释放元素。当元素距离可视区域较远时,移出DOM Tree且无任何引用。或者简单地把img标签的src属性改名为src-src(可随意)属性即可。

淘汰

淘汰算法:LRU-SP(Size-adjusted and Popularity-aware extension to Least Recently Used),即加入资源大小的考虑再进行“最近使用”淘汰。可参考此文

http://www.is.kyusan-u.ac.jp/~chengk/pub/papers/compsac00_A07-07.pdf

命中率

无论哪种Cache,命中率都是性能指标之一。对Memory Cache来说即非活动资源被使用的比例。从前面几节的信息可知,命中率的自然增长一般需要用户持续在同一个网站内浏览,因为同网站的资源复用率最高,例如引用的jQuery URL都一样。

从这点出发可知,中小网站引用大流量网站的资源CDN是有一定的加速效果的。(CDN参考 http://www.jq22.com/cdn/

按照统计,命中资源中的比例:图片 > JS > CSS。

Web开发须知的浏览器内幕 缓存与存储篇(1)的更多相关文章

  1. Web开发须知的浏览器内幕 缓存与存储篇(2)

    本文禁止转载,由UC浏览器内部出品. 3. HTTP Cache 综述 HTTP Cache是完全按照IETF规范实现的,最新的RFC规范地址是 https://tools.ietf.org/html ...

  2. Web开发基本准则-55实录-缓存策略

    续上篇<Web开发基本准则-55实录-Web访问安全>. Web开发基本准则-55实录-缓存策略 郑昀 创建于2013年2月 郑昀 最后更新于2013年10月26日 提纲: Web访问安全 ...

  3. Atitit.h5 web webview性能提升解决方案-----fileStrore缓存离线存储+http方案

    Atitit.h5 web webview性能提升解决方案-----fileStrore缓存离线存储+http方案 1. 业务场景 android+webview h5 css背景图性能提升1 2. ...

  4. web开发方面会遇到哪些缓存?分别如何优化

    Web缓存定义: Web缓存游走于服务器和客户端之间,这个服务器可能是源服务器(资源所驻留的服务器Add),数量可能是1个或多个. Web缓存就在服务器-客户端之间搞监控,监控请求,并且把请求输出的内 ...

  5. Web开发须知:URL编码与解码

    通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如,Url参数字符串中使用key ...

  6. web开发必备的浏览器常识

    浏览器内核: 1.使用Trident内核的浏览器:IE.Maxthon.TT.The World等: 2.使用Gecko内核的浏览器:Netcape6及以上版本.FireFox.MozillaSuit ...

  7. Django中web开发用md5加密图片名并存储静态文件夹

    一般在开发中,有的网站存在大量图片,首先图片的名称是不能重复的, 但是除了数据库可用的id以外我们可以用time模块中time.time()获取的时间来进行md5加密操作, 因为time模块所产生的时 ...

  8. web开发,关于jsp的常见问题,重复提交,防止后退。

    看了网上的,有几种方法:1 在你的表单页里HEAD区加入这段代码: <META HTTP-EQUIV="pragma" CONTENT="no-cache" ...

  9. web开发微信文章目录

    Web开发微信文章目录 2015-12-13 Web开发 本文是Web开发微信的文章目录.通过目录查看文章编号,回复文章编号就能查看文章全文. 回复编号查看全文,搜索分类名可以获得该分类下的文章.   ...

随机推荐

  1. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  2. jQuery EasyUI Datagrid组件的完整的基础DOM结构

    标题可能有点长,什么叫“完整的基础DOM结构”,这里“基础”的意思是指这个结构不依赖具体数据,不依赖Datagrid的view属性,只要存在Datagrid实例就会存在这样的基础DOM结构:而“完整” ...

  3. 配置 CentOS 7 安装位置

    红框里是CentOS 7安装程序检测到的硬盘,选择你想把系统安装到哪个硬盘当中. 点击 Add disk 按钮可以添加指定的附加设备或者网络设备(通过ISCSI.FCoE等方式添加硬盘) 此处设置分区 ...

  4. 100道C#面试题(.net开发人员必备)

    1. .NET和C#有什么区别 答:.NET一般指 .NET FrameWork框架,它是一种平台,一种技术. C#是一种编程语言,可以基于.NET平台的应用. 2.一列数的规则如下: 1.1.2.3 ...

  5. 【Guava】PreConditions来校验参数

    前置条件:让方法调用的前置条件判断更简单. 在我们的日常开发中,经常要对入参进行一定的参数校验,比如是否为空,参数的取值范围是否符合要求等等.这种参数校验如果我们单独进行校验的话,代码的重复率比较高, ...

  6. webpack使用 babili-webpack-plugin 报错 "original.line and original.column are not numbers"

    按照这个解决 https://github.com/chentsulin/electron-react-boilerplate/issues/1300 changing "babili-we ...

  7. [中英对照]The sysfs Filesystem | sysfs文件系统

    The sysfs Filesystem | sysfs文件系统 Abstract | 摘要 sysfs is a feature of the Linux 2.6 kernel that allow ...

  8. R语言数据重塑cbind+rbind+merge+ melt+cast

    R语言中的数据重塑是关于变化的数据分为行和列的方式.大多数R地数据处理的时候是通过将输入的数据作为一个数据帧进行.这是很容易提取一个数据帧的行和列数据,但在某些情况,当我们需要的数据帧的格式是不同的来 ...

  9. rvm的安装, 使用rvm, 安装ruby, 以及gem的使用 (转)

    http://blog.163.com/digoal@126/blog/static/1638770402012425111617904/ rvm 全称Ruby Version Manager,  确 ...

  10. flask框架的学习

    ---恢复内容开始--- 第一个flask程序讲解:1. 第一次创建项目的时候,要添加flask的虚拟环境.添加虚拟环境的时候,一定要选择到python这个执行文件.比如你的flask的虚拟环境的目录 ...