在浏览器地址栏中输入了一个URL,敲了回车后会发生什么?
从前端的视角去分析整个过程
重点:
- 浏览器渲染的基本流程
- 影响网页渲染因素
- 网页性能优化的方式
第一步:解析域名
浏览器在访问一个URL时会先解析其域名,一段URL大致分成以下几部分
例: https://www.example.com:443/path/to/myfile.html?key1=value1&key2=value2#Some
- 协议(protocol):
https - 域名(host):
www.example.com - 端口(port):
443 - 路径(path):
/path/to/myfile.html - 参数(query):
?key1=value1&key2=value2 - 锚点(fragment):
#Some
关键点
- 将域名解析成ip:浏览器会将域名解析成ip来访问
- 由近到远查询:解析过程中,浏览器会从本地缓存-->域名服务器的路径来查询,所以越是经常访问的域名查询到的速度就越快
优化点
- 在头部使用
dns-prefetch让浏览器预处理 - 使用第三方知名域名
第二步:建立连接
浏览器会在这一步尝试连接对方服务器,对于前端来说这个阶段优化空间不大,一般和服务器部署有关,服务器可以用CDN加速
第三步:发起请求
优化点
利用cookie传递初始化所需数据
第四步:下载网页
在这一步浏览器会检查响应头,判断是否使用缓存,是则启用缓存进入渲染阶段。否则下载网页,下载完成后进入渲染阶段。
在这一点值得注意的是,如果给HTML加缓存可能会出现更新问题。
第五步:渲染
关键点
- 浏览器会一边解析、一边渲染
- FCP(首屏渲染):第一次渲染发生在
<head>加载完成后,一般不会影响“总渲染时间”,但是对用户体验影响很大 <link>不会阻塞渲染<script>可能会阻塞渲染<script>:js的加载解析和执行会阻塞渲染。HTML解析器在遇到js时会暂停文档解析,将控制权交由js引擎,在js引擎解析执行完毕后再从断点恢复继续文档解析,<script defer>:defer属性表示延迟执行引入的JavaScript,即这段Javascript加载时html并未停止解析,这两个过程是并行的。当整个document解析完毕之后再执行脚本文件,再DomContentLoaded事件触发之前完成。多个脚本按顺序执行。<script async>: async属性表示异步执行引入的JavaScript,与deder的区别在于,如果已经加载好,就会开始执行,也就是说它的执行仍然会阻塞文档的解析,只是它的加载过程不会阻塞。多个脚本的执行顺序无法保证。<script type='module'>会按需加载
- 图片,视频等资源一般不会阻塞渲染
- 渲染会发生在标签闭合时
优化点
速度
- 在
<head>中放关键样式,但是不要放会阻塞的脚本 - 尽量将
<script>放在<body>后,添加defer或async属性 - 首屏HTML要放在一个闭合标签里
- 减少请求数量,业务无关的代码,建议最后加载
- 减少首次渲染内容,使用lazy-load加载图片等资源
- 压缩图片:高压缩比图片---webp位图(除IE11)、矢量图svg
- 压缩视频:尽量用MP4
- 使用视频替代gif 体积相差接近10倍
- 增加缓存时间
布局稳定
- 使用骨架屏
- 减少使用 web fonts
- 给图片添加起始尺寸
- 避免后期加载的内容导致页面变化和抖动
代码
- 代码分模块,按需加载
- 使用es module