前端性能优化
性能优化常见的办法:
一、资源压缩与合并
资源压缩与合并 主要包括这些方面:
html压缩,CSS压缩,JS的压缩和混乱以及合并。
1、html 压缩
html代码压缩就是压缩这些在文本文件中有意义,但是在HTML中不显示的字符,包括空格,制表符,换行符等,还有一些其他意义的字符,如HTML注释也可以被压缩。
如何进行 html 压缩?
(1)、使用在线网站进行压缩(开发过程中一般不用)
(2)、nodejs 提供了html-minifier工具,利用其他项目构建工具
(3)、后端模板引擎渲染压缩
2、CSS 压缩
css代码压缩简单来说就是无效代码删除和css语义合并
如何进行 CSS 压缩?
(1)、使用在线网站进行压缩(开发过程中一般不用)
(2)、nodejs 提供了html-minifier工具,利用其他项目构建工具
3、JS 的压缩和混乱
js的压缩和混乱主要包括以下这几部分:
(1)、无效字符的删除
(2)、剔除注释
(3)、代码语义的缩减和优化
(4)、代码保护(代码逻辑变得混乱,降低代码的可读性,这点很重要)
如何进行JS 的压缩和混乱?
(1)、使用在线网站进行压缩(开发过程中一般不用)
(2)、使用html-minifier工具,利用其他项目构建工具
(3)、使用uglifyjs2对js进行压缩
注:html压缩可有可无,但css压缩与js的压缩和混乱必须要有!
4、文件合并
压缩合并css和js可以减少网站http请求的次数
如何实现文件合并?
(1)、使用在线网站进行文件合并
(2)、使用nodejs实现文件合并(gulp、webpack等)
二、非核心代码异步加载的方式
1、异步加载的方式
异步加载的三种方式:async、defer、动态脚本创建
(1)、async 方式
1>.async属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持
2>.async属性规定一旦脚本可用,则会异步执行
3>.async属性仅适用于外部脚本
4>.如果是多个脚本,该方法不能保证脚本按顺序执行
<script type="text/javascript" src="xxx.js" async="async"></script>
(2)、defer 方式
1>.兼容所有浏览器
2>.defer属性规定是否对脚本执行进行延迟,直到页面加载为止
3>.如果是多个脚本,该方法可以确保所有设置了defer属性的脚本按顺序执行
4>.如果脚本不会改变文档的内容,可将defer属性加入到script标签中,以便加快处理文档的速度
(3).动态创建脚本
动态创建script标签在还没定义 defer 和 async 前,异步加载的方式是动态创建script,通过window.onload方法确保页面加载完毕再将script标签插入到DOM中,具体代码如下:
function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function() { addScriptTag("js/index.js"); }
2、异步加载的区别
(1)、defer是在HTML解析完之后才会执行,如果是多个,按照加载的顺序依次执行
(2)、async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关
三、利用浏览器缓存
对于web应用来说,缓存是提升页面性能同时减少服务器压力的利器。
浏览器缓存类型
浏览器缓存 分为 强缓存 和 协商缓存。
强缓存:
不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码,并且size显示from disk cache或from memory cache;
相关header:
Expires: response header里的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存
Cache-Control: 这是一个相对时间,在配置缓存的时候,以秒为单位,用数值表示。当值设为max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。比如Cache-Control:max-age=300
两者同时存在的话,Cache-Control优先级高于Expires
协商缓存:
向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;另外协商缓存需要与cache-control共同使用
相关header:
Last-Modified 和 If-Modified-Since
ETag 和 If-None-Match
缓存的机制:
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,
若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,
若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存。
四、使用 CDN
大型Web应用对速度的追求并没有止步于仅仅利用浏览器缓存,因为浏览器缓存始终只是为了提升二次访问的速度,
对于首次访问的加速,我们需要从网络层面进行优化,最常见的手段就是CDN(Content Delivery Network,内容分发网络)加速。
通过将静态资源(例如javascript,css,图片等等)缓存到离用户很近的相同网络运营商的CDN节点上,不但能提升用户的访问速度,还能节省服务器的带宽消耗,降低负载。
CDN是怎么做到加速的呢?
其实这是CDN服务商在全国各个省份部署计算节点,CDN加速将网站的内容缓存在网络边缘,不同地区的用户就会访问到离自己最近的相同网络线路上的CDN节点,
当请求达到CDN节点后,节点会判断自己的内容缓存是否有效,如果有效,则立即响应缓存内容给用户,从而加快响应速度。
如果CDN节点的缓存失效,它会根据服务配置去我们的内容源服务器获取最新的资源响应给用户,并将内容缓存下来以便响应给后续访问的用户。
因此,一个地区内只要有一个用户先加载资源,在CDN中建立了缓存,该地区的其他后续用户都能因此而受益。
五、预解析DNS
资源预加载是另一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。
通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。
例如,我们将来可从 example.com 获取图片或音频资源,那么可以在文档顶部的 标签中加入以下内容:
<link rel="dns-prefetch" href="//example.com">
当我们从该 URL 请求一个资源时,就不再需要等待 DNS 的解析过程。该技术对使用第三方资源特别有用。
通过简单的一行代码就可以告知那些兼容的浏览器进行 DNS 预解析,这意味着当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了,从而节省了宝贵的时间。
另外需要注意的是,浏览器会对a标签的href自动启用DNS Prefetching,所以a标签里包含的域名不需要在head中手动设置link。但是在HTTPS下不起作用,需要meta来强制开启功能。
这个限制的原因是防止窃听者根据DNS Prefetching推断显示在HTTPS页面中超链接的主机名。下面这句话作用是强制打开a标签域名解析
<meta http-equiv="x-dns-prefetch-control" content="on">