浏览器加载资源的过程可以大致分为下面的4个步骤: 资源分类 ===> 资源安全策略检查 ===> 资源优先级计算 ===> 根据优先级下载资源
- 浏览器对页面所有的资源进行了分类
- 根据浏览器相关的安全策略, 来决定资源加载的权限
- 接着对资源的加载的优先级进行计算和排序
- 最后根据优先级顺序来下载资源
接下来按照这个顺序给大家解说。
资源分类
将常见的资源类型分为下面的10种:
- 主资源:
HTML
- 样式资源:
css
- 字体资源:
font
(也就是Icon字体库) - 脚本资源:
script
- 图片:
image
- 混合类型资源: 常见的就是
xhr
- 矢量图形资源:
svg
media
: 多媒体资源:vedio, audio, TextTrack(video的字幕)
manifest
: 应用程序缓存资源perfetch
:预读取资源
type | introduction |
---|---|
kMainResource | html |
kImage | image |
kCSSStyleSheet | css |
kScript | js |
kFont | font |
kRaw | ajax |
kSVGDocument | SVG |
kXSLStyleSheet | XSLT |
kLinkPrefetch | Link prefetch, dns-prefetch |
kTextTrack | TextTrack |
kImportResource | HTML Imports |
kMedia | media |
kManifest | HTML5 application resource cache |
kMock | test type |
安全策略检查(Content-Security-Policy,简称CSP)
也就是我们所说的网络白名单,限制浏览器对各类资源的加载,提高网站的安全性。一种常用的应用就是通过限制非信任域名的脚本加载来预防XSS攻击
白名单的设置可以分为两种:
- 页面
HTTP Response
头的Content-Security-Policy
字段来限制; - 通过
<meta>
标签来设置
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; style-src nos.netease.com kaola.com;">
script-src
和 style-src
是资源的类型,常见的还有 img-src
;
self
表示当前网页的域名
nos.netease.com kaola.com
表示信任的域名 多个域名可以使用空格连接
SCP还可以用于站点请求协议升级过度(http转https)
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
设置这个meta标签以后,浏览器会将https页面中的所有 http
请求自动升级到 https
;例如:当我们将全站中的 http
转成 https
时,对于原有的 http
强制转成 https
的形式发送,且不会报错。当然这个时候是需要服务器端支持的。
用于阻止Mixed Content
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
混合内容 Mixed Content
就是指 https
页面中含有 http
的请求,这种在安全链接中混合了非安全请求内容就叫做混合内容(一般出现这种情况的时候可以在控制台中看到警告信息)
通过上面的标签来阻止所以类型的非安全链接请求,这样包括图片、音频、视频等资源也将会被拦截报错。
资源优先级计算
从浏览器内核考虑将资源分为5个等级(不同浏览器的等级名称可能不一样): VeryHigh ===> High ===> Medium ===> Low ===> VeryLow
根据资源的类型来设定默认优先级。 对于每一类资源浏览器都有一个默认的加载优先级规则:
-
VeryHigh: html、css、font这三类资源的优先级最高
-
High: HTML Imports(将一个HTML文件导入到其他HTML文档中,
<link href="import/post.html" rel="import" />
)、script、xhr请求 -
Medium: manifest 应用程序缓存资源
-
Low: 图片、音频、视频、SVG、TextTrack(video的字幕)
-
VeryLow: perfetch预读取的资源
根据一定的实际规则,对优先级进行调整
初始优先级设置好以后,浏览器会根据资源的实际属性和位于文档中的位置等方面,对优先级进行调整,来确定出最终的加载优先级顺序
-
对于
XHR
请求资源:将同步XHR
请求的优先级调整为最高。XHR
请求可以分为同步请求和异步请求,浏览器会把同步请求的优先级提升到最高级,以便尽早获取数据、加快页面的显示 -
对于图片资源:会根据图片是否在可见视图之内来改变优先级。 图片资源的默认优先级为Low。现代浏览器为了提高用户首屏的体验,在页面渲染时会计算图片资源是否在首屏可见视区以内,在的话,会将这部分可见图片(Image in viewport)资源的优先级提升为High。
-
对于脚本资源:浏览器会将根据脚本所处的位置和属性标签分为三类:
A:添加了
defer/async
属性标签的脚本的优先级会全部降为LowB:没有添加
defer/async
属性的脚本,且页面是否已经加载了一张非preload
图片,来判断脚本在文档中的位置。如果页面已经加载了一张图片就认为这个script是页面偏底部的位置, 就把它的优先级调成mediumC:否则就设置为high
如何对资源的加载进行优化
通过上面的安全策略和优先级的设置来加载和阻塞资源,我们可以通过优化资源的加载优先级顺序,来有效提高页面的加载响应速度。我们可以通过下面的技术来进行优化。
preload
和 prefetch
它们都属于预加载性能优化技术。预先告知浏览器某些资源可能在将来会被使用到,让浏览器对这部分资源进行提前加载
<link rel="preload" href="xxxx.js">
<link rel="preload" href="xxx.jpg">
Prefetch包括资源预加载、DNS预解析、http预连接和页面预渲染。
<link rel="prefetch" href="test.css">
<link rel="dns-prefetch" href="//haitao.nos.netease.com">
<link rel="prefetch" href="//www.kaola.com">
<link rel="prefetch" href="//m.kaola.com">
最后两个分别是:http
预连接和页面预渲染。
preload
和 prefetch
的区别
preload
告诉浏览器预先请求当前页需要的资源,提高这些资源请求的优先级。对于那些本来请求优先级较低的关键请求,我们可以通过设置 preload
来提升这些请求的优先级。prefetch
告诉浏览器将来可能在其他页面(非本页面)或将来某个时候可能使用到的资源,那么浏览器会在空闲时,就去加载这些资源,最常见的 dns-prefetch
。
看看浏览器对 preload
和 prefetch
的兼容性如何



localStorage
通常可以利用LocalStorage来对部分请求的数据和结果进行缓存,省去发送http请求所消耗的时间,从而提高网页的响应速度。 这类做法在移动端应用已经十分广泛。
最后
通过上面的分析,我们已经知道了浏览器对资源加载的过程,和如何进行优化。最后那么来捋一捋js和css资源放在文档不同位置时对其他资源的阻塞情况

上面的三种情况,很明显第一种和最后一种更优。那 <script>
放在头部位置和尾部有什么不一样。通过观察css的位置可以知道,第三种情况下留给用户的白屏的时间更短,因为在相同的情况下css越靠前那么就会越早完成解析,页面就也早呈现给用户。这就是为什么很多项目都将js资源放在文档底部的原因。
最后
希望疫情早点结束,为那些奋斗在一线的医护人员加油。(~在家都快憋疯了~)