前端面试,总是会被问到这样一类问题:

为什么最好把 CSS 的<link>标签放在<head></head>之间?为什么最好把 JS 的<script>标签放在</body>之前?

为什么JS 会阻塞DOM解析,而CSS会阻塞渲染??

<script>标签当中的async和defer都是做什么的???

如何优化关键渲染路径????

好了好了,其实理解了关键渲染路径之后,这些问题会变得so easy。妈妈就再也不用担心我的前端面试了。那么,我们就来看看,什么是关键渲染路径

关键渲染路径都有哪些步骤呢?

关键渲染路径一共分为6个步骤,如下图所示:

具体分为:

  1. 创建DOM树
  2. 创建CSS树
  3. 执行脚本(就是JavaScript)
  4. 生成渲染树
  5. 布局
  6. 绘制

我们接下来一步一步地分析。

创建DOM树

下面是一段很简单的HTML代码:

<!DOCTYPE html>
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"><title>Critical Path</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body>
</html>

浏览器读到这一段代码之后,会把标签转换成DOM树中对应的节点,保留每个节点的属性,并根据节点与节点之间的父子关系,生成树形结构:

这就是DOM树。

创建CSSOM树

上个例子中,当浏览器在创建DOM树的时候,会遇到外部CSS标签:<link href=”style.css” rel=”stylesheet”>。浏览器这个时候会发出http请求,向服务器请求这个文件的内容:

body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }

浏览器收到这个文件之后,会把文件中的CSS转换成CSSOM树。这个过程并不是更新现在这棵DOM树,而是同时去生成一个新的,完全独立的树形结构。 DOM树和CSSOM树是两个不同的数据结构。

生成渲染树

上个例子中,当DOM树和CSSOM树都准备好了之后,浏览器就会合并这两棵树,生成渲染树,如下图所示:

有几点需要注意的:

  1. 我们可以看到,渲染树是需要DOM树和CSSOM树建立完成之后才能够生成的,因此,HTML和CSS都是会阻塞渲染的!
  2. 然而,没有CSS的页面看起来是很糟糕的,因此,我们应该尽早完成CSS的下载与解析,因此CSS标签应当被放到head当中。
  3. <head>以及其内部的标签不会出现在渲染树当中
  4. 被隐藏的属性也不会出现在渲染树当中,例如例子中display: none的span标签。注意:visibility: hidden的元素虽然被隐藏,但是仍在文档流中占据空间,不会从渲染树当中移除。

执行脚本

如果代码当中有script标签,那么浏览器就会下载(这个只针对外联JS代码)然后运行JS代码。

有几点需要注意的:

  1. JS代码可以修改DOM结构,更改CSS样式,因此,JS可以查询和修改DOM树和CSSOM树。
  2. 脚本在哪里插入,就会在哪里执行。浏览器解析DOM的时候,如果遇到script标签,会停止解析DOM,JS引擎会运行script中的脚本,运行结束后,才继续解析DOM。因此,脚本会阻塞DOM的解析。
  3. 如果脚本想要修改CSSOM的内容,而此时,CSSOM还未构建完成,那么浏览器会选择先下载并创建CSSOM,然后再运行脚本。

因此,script标签的位置很重要,我们往往选择在</body>之前加入script,这样可以保证DOM树的解析,把页面尽早呈现给用户。

那么,什么是async,什么是defer?

Async是不会阻塞关键渲染路径的,async告诉浏览器,如果遇到带有async的script标签时,这段脚本的下载不会阻塞浏览器构建DOM树,浏览器向服务器发送script请求的时候,仍然可以继续构建DOM树。

Defer也是告诉浏览器立即下载脚本文件(同样不会阻塞DOM),但是延迟到整个页面都解析完毕之后再运行。

用一张图表示就是:

布局

上面的例子当中,有这样一段代码:

<meta name="viewport" content="width=device-width,initial-scale=1">

这段代码中,width=device-width是告诉浏览器页面宽度要符合设备的DIP(设备独立像素)宽度,而initial-scale=1则告诉浏览器DIP与设备像素之间的比例为1(这个不懂也没关系,以后有空的话,我也会发文给大家简单解释解释)。

浏览器会从根节点开始,确定每个节点在页面上的大小和位置,使用盒模型把每个元素定位在页面当中。

绘制

最后一步,把渲染树上的节点绘制在页面当中,并画上花花绿绿的样式。

如何优化关键渲染路径

优化关键渲染路径,主要从三个方面下手:

  1. 减少文件大小:最小化文件;压缩文件;以及缓存文件
  2. 减少关键资源的数量:CSS和JS文件放在bundle当中;在link上使用media query(media=”print”文件中的样式只有在打印时才会被使用,因此,media=”print”告诉浏览器,我并不会阻塞关键渲染路径);在script标签中使用async或者defer
  3. 减少关键渲染路径的长度(这是获取所有关键资源所需的往返次数或总时间)

结束

希望看完这篇文章之后,你能够回答开头提出的那几个问题了。祝大家前端学习一切顺利。

js修改背景图片路径_前端面试题————关键渲染路径(Critical Rendering Path)...相关推荐

  1. js 定时网页点击_前端面试题整合(JS进阶篇)(二)

    Ajax 是什么? 如何创建一个Ajax? AJAX全称是Asychronous JavaScript And Xml(异步的 JavaScript 和 XML) 它的作用是用来实现客户端与服务器端的 ...

  2. js 定时网页点击_前端面试题熬夜吐血(js进阶篇)

    Ajax 是什么? 如何创建一个Ajax? AJAX全称是Asychronous JavaScript And Xml(异步的 JavaScript 和 XML) 它的作用是用来实现客户端与服务器端的 ...

  3. JS——修改背景图片

    问题描述 使用JS修改元素的背景图片 解决方法 1 使用 css() 给元素添加背景图片 这种方法添加的样式优先级相当于行内样式,会覆盖掉优先级比他低的样式 代码如下: $("css选择器& ...

  4. css grid 自动高度_前端面试题:关于CSS布局

    金三银四求职季 各位同学面试是否顺利呢? 在这关键时刻 小狮送上前端面试题一份 有用就赶紧收藏起来吧!!! 1 Q:三栏布局,高度已知,左右两栏固定,中间自适应的三栏布局有几种实现方式,各自的优缺点是 ...

  5. dom vue 加载完 执行_前端面试题——Vue

    前言 前几天整理了一些 html + css + JavaScript 常见的面试题(https://segmentfault.com/u/youdangde_5c8b208a23f95/articl ...

  6. dom vue 加载完 执行_前端面试题Vue

    前言 前几天整理了一些 html + css + JavaScript 常见的面试题,然后现在也是找了一些在 Vue 方面经常出现的面试题,留给自己查看消化,也分享给有需要的小伙伴. 如果文章中有出现 ...

  7. 如何获取元素在父级div里的位置_前端面试题--元素的BFC特性和实例

    1.BFC 是什么? Block Formatting Contexts 块级格式化上下文.(不懂? 没关系,后文有介绍.) 2.为什么需要BFC? 在传统布局中出现的问题需要一种统一的解决方案. 首 ...

  8. react全局方法_前端面试题 ---react

    高阶组件相关 什么是高阶组件,它有哪些运用? 高阶组件就是一个函数,接收一个组件,经过处理后返回后的新的组件: 高阶组件,不是真正意义上的组件,其实是一种模式: 可以对逻辑代码进行抽离,或者添加某个共 ...

  9. php 统计二维数组次数最多_前端面试题(数组篇)

    前端面试中,数组是少不了的.因为数组使用度比较频繁,我在项目中就经常使用.JavaScript拼接Html,数据结构计算,等等. 汇总一下面试中数组会问到的几个问题,这个问题在面试经常被问到,但是一般 ...

最新文章

  1. Android之调用js常见错误
  2. Delphi IDE扩展工具,在IDE中增加Google翻译器
  3. 利用redis实现分布式锁:加锁与解锁
  4. 找出不是两个数组共有的元素
  5. [luoguP1013] 进制位(搜索)
  6. 物联网-移远M26模块OpenCPU开发第3讲(看门狗)
  7. 洛谷 P1508 Likecloud-吃、吃、吃
  8. Android动态切换主题
  9. php utf8 正则中文表达式
  10. Mate7微信指纹支付来了 比Touch ID整合微信早一点
  11. 计算机在线考试系统监考,在线考试系统怎样实现监考功能
  12. 正确的java学习顺序--刚入门的同学可以看这里
  13. (实验)使用Protel 99se绘制2114存储器芯片(详细)
  14. Python实现简单的用户管理系统
  15. Activity任务栈
  16. diskgenius克隆硬盘无法启动_克隆分区
  17. c++ RMI demo(使用RCF库)
  18. 古时候的汉法,现代社会的红光光浴-种光光学
  19. 3.提取线稿(PS)
  20. ANO匿名飞控分析(2)— 任务调度

热门文章

  1. log4net简单配置内容
  2. 当页面上的某个控件回发时,保持滚动条位置的。
  3. Nest入门教程 - 初识Providers
  4. 【编程】不同编程语言的用处(图解)
  5. 【Java】数组的使用
  6. BUUCTF寒假刷题-Web
  7. 常用系统级加压工具简介
  8. fortran 读整行_我整周读过的最有趣的东西
  9. Java 猜字谜游戏
  10. php查找存储引擎,php-如何找到MySQL临时表存储引擎