【5】前端

【前端】

一、前端性能优化策略

  • 减少 HTTP 请求
  • CSS 放在头部
  • JS 放在尾部
  • 避免使用 CSS 表达式
  • 精简 JS
  • 使用外部 CSS 和 JS 文件
  • 删除重复脚本
  • 压缩组件
  • 避免重定向
  • 使用缓存
  • 使用 CDN
  • 减少 CDN 查找

CSS 放在头部,JS 放在尾部的原因:

假设我们将CSS文件放在尾部,那么当浏览器开始渲染页面时,会采用一些初始样式(或者浏览器默认的样式),直到到达尾部的CSS文件时,浏览器还需根据CSS文件重新渲染页面,这样就会造成巨大的开销,影响性能。所以,CSS文件最好放在头部,使得浏览器减少一次页面的渲染。

假设浏览器正在渲染页面,碰到了JS文件,浏览器便会停止渲染页面,转而下载并执行JS文件,直到JS文件下载并执行完成,才会重新开始渲染页面,这也就造成了页面渲染的阻塞。所以,JS文件最好放在尾部,防止阻塞页面的渲染。

其中,对于JS文件的下载,当然现在浏览器已经支持并行下载,但仍然会阻塞图片等的下载和渲染;对于JS文件的执行顺序,无论是外部JS还是内部JS,仍然是按顺序执行,等上一个<script>执行完成才会执行下一个。

图片的下载和渲染有两种方式:预加载和懒加载。

图片预加载:就是在网页全部加载完成之前,提前加载图片,当用户需要查看时可直接从本地缓存中渲染,以提供给用户更好的体验,减少等待的时间。

图片懒加载:延迟加载图片或符合某些条件时才加载图片。

两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。

高性能的javascript之加载顺序与执行原理篇_基础知识_脚本之家

二、跨域解决方案及其原理

同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个IP地址,也非同源。

常见的跨域场景(不允许通信):

(1)不同协议,同一域名:http://www.domain.com/a.js 和 https://www.domain.com/b.js

(2)同一域名,不同端口:http://www.domain.com:8000/a.js 和 http://www.domain.com/b.js

(3)不同域名:http://www.domain1.com/a.js 和 http://www.domain2.com/b.js

(4)主域相同,子域不同:http://www.domain.com/a.js 和 http://x.domain.com/b.js 和 http://domain.com/c.js

(5)域名和域名对应相同IP:http://www.domain.com/a.js 和 http://192.168.4.12/b.js

跨域解决方案:

(1)通过 jsonp 跨域

(2)document.domain + iframe 跨域:仅限主域相同,子域不同的跨域场景。

(3)location.hash + iframe 跨域:a欲与b跨域相互通信,通过中间页c来实现。

(4)window.name + iframe 跨域

(5)postMessage 跨域

(6)跨域资源共享(CORS):只需要服务端设置Access-Control-Allow-Origin即可。

(7)nginx 代理跨域

(8)nodejs 中间件代理跨域

(9)WebSocket 协议跨域

跨域解决方案的原理

三、link 和 import 的区别

link 属于 XHTML 标签,而 @import 是 CSS 提供的。

(1)引用的方式不同:

link(外部引用): <link rel="stylesheet" href="xxx.css"  type="text/css" />
 
@import(导入式): @import url(xxx.css);

(2)放置的位置不同:link 一般放在 head 标签中,而 @import 必须放在 <style  type="text/css"> 标签中。

(3)加载方式不同:link 会和 dom 结构一同加载渲染,而 @import 只能等 dom 结构加载完成以后才能加载渲染页面。

(4)兼容性不同:@import 只能在 IE6 以上才能识别,而 link 是 XHTML 标签,无兼容问题。

(5)样式权重不同:link 方式的样式的权重高于 @import。

(6)改变样式:link 支持使用 JavaScript 改变样式,而 @import 不可以。

(7)加载内容不同:link 除了可以加载 css 文件以外,还可以加载 MIME 类型的文件;而 @import 只能加载 css 文件。

四、浏览器内核

  • IE、傲游、Avant、腾讯TT (trident内核)
  • Mozilla Firefox (gecko内核)
  • Safari (webkit内核)
  • Chrome (Blink内核)
  • Opera (原为Presto内核,现为Blink内核)

五、浏览器兼容问题及其解决方案

问题一:在不加样式控制的情况下,标签默认的外补丁(margin)和内补丁(padding)不同

解决方案: CSS设置 *{ margin:0; padding:0; }

问题二:块级属性标签 float 之后,如果有左右 margin,那么在 IE6 中显示的 margin 比设置的大

解决方案: 在float的标签样式中加入 { display: inline; }, 将其转化为行内属性

问题三:行内属性标签,在设置 display:block 之后,如果采用 float 布局,同时又有左右 margin 的情况下,那么在 IE6 中显示的间距有 bug

解决方案: 在 { display:block; } 后面加入 { display:inline; display:table; }

问题四:如果给标签设置较小的高度(一般小于10px),那么在IE6,IE7和遨游中这个标签的高度会超出你设置的高度

在IE6、IE7和遨游中,这个标签的高度不受你设置的高度的控制,它会达到默认的行高。这是因为 IE8 之前的浏览器都会给标签一个最小默认的行高的高度,即使标签是空的,这个标签的高度还是会达到默认的行高。

解决方案: 给超出高度的标签设置 { overflow:hidden; } 或者设置行高 { line-height } 小于你设置的高度

问题五:如果给标签设置最低高度 min-height,会出现不兼容的情况

解决方案: 如果我们要设置一个标签的最小高度是200px,需要进行的设置为:
{
    min-height:200px; 
    height:auto !important; 
    height:200px; 
    overflow:visible;
}

问题六:图片之间默认有间距

几个 img 标签放在一起的时候,有些浏览器会有默认的间距,加了问题一中提到的通配符也不起作用。

解决方案: 将 img 设置为 float 属性

问题七:格式为PNG24的图片在IE6浏览器上会出现背景

解决方案:把图片改成 PNG8 格式

问题八:设置透明度(兼容所有浏览器)

.tran_class {   
    filter: alpha(opacity=50); // IE浏览器 (trident内核)
    -moz-opacity: 0.5;  // 老版Mozilla firefox (gecko内核) 
    -khtml-opacity: 0.5;   // 老版Safari (webkit内核)
    opacity: 0.5;   // 支持opacity的所有浏览器,如:Chrome (Blink内核)、opera (以前是presto内核,现在改用google chrome的Blink内核)
}

问题九: IE6,IE7中 ol 的序号全为1,不递增

解决方案: li设置样式 { display: list-item }

问题十: IE6,IE7不支持 display:inline-block

解决方案: 设置 inline, 并触发 haslayout
{ display:inline-block; *display:inline; *zoom:1 }

问题十一: 使用 hack 解决浏览器兼容问题

不同的浏览器对CSS的解析不同,会导致生成的页面效果不同。通过使用 hack 可以解决浏览器兼容问题(针对的更多是 老式/旧版本 浏览器),但不推荐使用,因为当代码量多时,编写复杂度会变高,还可能会在浏览器更新之后产生更多的兼容问题。

hack 可以理解为不同浏览器识别的标识符。

(1)五大浏览器的hack

div {
    transform: rotate(90deg);         /* 标准模式 */
    -moz-transform: rotate(90deg);    /* Firefox */
    -webkit-transform: rotate(90deg); /* Safari and Chrome */
    -o-transform: rotate(90deg);      /* Opera */
    -ms-transform: rotate(90deg);     /* IE */
}

(2)CSS属性hack

IE6能识别 下划线_ 和 星号* ,但不能识别 !important
IE7能识别 星号* 和 !important ,但不识别 下划线_
Firefox 能识别 !important ,但不识别 下划线_ 和 星号*
书写顺序:FF IE7 IE6
 
比如这样一个CSS设置:
{ 
    height:300px; 
    *height:200px; 
    _height:100px; 
}
 
在IE6中从上往下读,直到_height,把高度设置成了100px;
在IE7中从上往下读,直到*height,把高度设置成了200px;
在其他浏览器中,把高度设置成了300px。

(3)CSS选择符hack

IE6能识别*html .class{}
IE7能识别*+html .class{} 或者 *:first-child+html .class{}

(4)条件注释法:这种方式是 IE 浏览器专有的 hack 方式,微软官方推荐使用。 

问题十二:获取自定义属性

IE浏览器下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性。

Firefox浏览器下,只能使用getAttribute()获取自定义属性。

解决方案:统一使用 getAttribute() 获取自定义属性

问题十三:Chrome 浏览器的中文界面下默认会将小于 12px 的文本强制按照 12px 显示

解决方案:加入 CSS 属性 {-webkit-text-size-adjust: none; }

问题十四:超链接访问过后 hover 样式就不出现了;被点击访问过的超链接样式不再具有 hover 和 active 了

解决方案:改变 CSS 属性的排列顺序:
L-V-H-A :  a:link {} a:visited {} a:hover {} a:active {} 

问题十五:even对象

IE浏览器下,even对象有x,y属性,但是没有pageX,pageY属性。

Firefox浏览器下,event对象有pageX,pageY属性,但是没有x,y属性。

解决方案:条件注释
缺点:在IE浏览器下可能会增加额外的 HTTP 请求。

六、从输入网址到最后浏览器呈现页面内容,中间发生了什么?

(1)输入网址,浏览器,发送UDP包给DNS服务器,通过DNS解析得到网址的IP地址(即服务器的IP),并将IP地址缓存。

(2)客户端(浏览器)和服务器端之间建立TCP连接:由于TCP邮差需要知道4个东西(本机IP,本机端口,服务器IP,服务器端口),现在只知道了本机IP,服务器IP, 两个端口怎么办?其中,本机端口很简单,操作系统可以给浏览器随机分配一个, 服务器端口更简单,用的是一个“众所周知”的端口,HTTP服务就是80(HTTPS服务就是443), 我们直接告诉TCP邮差就行。经过三次握手以后,客户端和服务器端的TCP连接就建立起来了! 

(3)浏览器发送HTTP请求。

(4)Web服务器处理请求,并将HTTP Response(一个HTML页面)返回给浏览器。

(5)浏览器再次发起请求:由于这个HTML页面中可能引用了大量其他资源,例如JS文件,CSS文件,图片等,这些资源也位于服务器端,并且可能位于另外一个域名下面。所以浏览器只好一个个地下载,从使用DNS获取IP开始,之前做过的事情还要再来一遍。

(6)当服务器把JS,CSS这些文件发送给浏览器时,会告诉浏览器这些文件什么时候过期(使用Cache-Control或者Expire),浏览器可以把文件缓存到本地,当第二次请求同样的文件时,如果不过期,直接从本地取就可以了。如果过期了,浏览器就可以询问服务器端,文件有没有修改过?(依据是上一次服务器发送的Last-Modified和ETag),如果没有修改过(304 Not Modified),还可以使用缓存。否则的话服务器就会把最新的文件发回到浏览器。

(7)现在浏览器拥有了 HTML、CSS 和 JavaScript(可以修改 DOM Tree),开始进行渲染

  • HTML,浏览器把它解析成 DOM Tree;CSS,浏览器把它解析成 CSS Rule Tree
  • DOM Tree 和 CSS Rule Tree 解析完成之后,被附加到一起,形成渲染树 Render Tree
  • (重排 - Reflow) 计算节点信息:根据渲染树计算每个节点的几何信息
  • (重绘 - Repaint) 渲染绘制:根据计算好的节点信息,渲染绘制整个页面

最后,我们就能看到呈现的页面了。

七、重排和重绘

重排:若渲染树的部分节点更新,且尺寸变化,就会发生重排。

重绘:若渲染树的部分节点更新,但不改变其他节点,就会发生重绘。

PS:重绘不一定导致重排,但重排一定会导致重绘。重排会产生比重绘更大的开销。

触发重排:

  • (1)页面第一次渲染:在页面发生首次渲染的时候,所有组件都要进行首次布局,这是开销最大的一次重排
  • (2)浏览器窗口尺寸改变
  • (3)元素位置和尺寸(宽、高、内外边距、边框等)发生改变的时候
  • (4)增加或删除DOM节点
  • (5)内容发生改变(文字数量或图片大小等等)
  • (6)元素字体大小变化
  • (7)激活CSS伪类(例如::hover) 
  • (8)增加或修改样式,设置style属性
  • (9)查询某些属性或调用某些方法,如:调用getComputedStyle方法,或者IE里的currentStyle时,也会触发重排
  • (10)display:none —— 设置该属性的元素将会消失,不占据空间

触发重绘:

  • (1)visibility:hidden —— visibility 属性规定元素是否可见。即使不可见的元素也会占据页面上的空间。
  • (2)outline —— outline (轮廓)是绘制于元素周围的一条线,位于边框边缘的外围。轮廓线不会占据空间,也不一定是矩形。
  • (3)背景颜色:color、background-color

如何减少重排和重绘以提升页面性能:

  • (1)样式集中改变。
  • (2)DOM离线化。
  • (3)批量添加DOM。
  • (4)复制节点,在副本中修改,然后直接替换当前的节点。
  • (5)降低受影响的节点:在页面顶部插入节点将影响后续所有节点,而绝对定位元素的改变会影响较少的元素,将position属性设置为absolute或fixed
  • (6)分离读写操作。
  • (7)缓存布局信息。
  • (8)使用 css spirit,也叫 css 精灵,它将所有的图片放到一张图片上,然后通过定位来实现图片的使用。

参考:前端性能优化:细说浏览器渲染的重排与重绘_慕课手记

END

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值