浏览器层面

减少Http请求

HTTP协议是无状态的应用层协议,意味着每次HTTP请求都需要建立通信链路、进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少HTTP请求的数目可有效提高访问性能。

减少HTTP的主要手段是合并CSS、合并JavaScript、合并图片。将浏览器一次访问需要的JavaScript、CSS合并成一个文件,这样浏览器就只需要一次请求。图片也可以合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移响应鼠标点击操作,构造不同的URL。

使用浏览器缓存

对一个网站而言,CSS、JavaScript、Logo、图标这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次HTTP请求都需要的,如果将这些文件缓存在浏览器中,可以极好地改善性能。通过设置HTTP头中Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。

在某些时候,静态资源文件变化需要及时应用到客户端浏览器,这种情况,可通过改变文件名实现,即更新 JavaScript 文件并不是更新 JavaScript 文件内容,而是生成一个新的JS文件并更新HTML文件中的引用。

使用浏览器缓存策略的网站在更新静态资源时,应采用逐量更新的方法,比如需要更新10个图标文件,不宜把10个文件一次全部更新,而是应一个文件一个文件逐步更新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服务器负载骤增、网络堵塞的情况。

启用压缩

在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。文本文件的压缩效率可达80%以上,因此HTML、CSS、JavaScript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,而服务器资源不足的情况下要权衡考虑。

具体可以参考:传送

CSS放在页面最上面、 JavaScript 放在页面最下面

浏览器会在下载完全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。 JavaScript 则相反,浏览器在加载 JavaScript 后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此 JavaScript 最好放在页面最下面。但如果页面解析时就需要用到 JavaScript ,这时放在底部就不合适了。

CDN加速

CDN(Content Distribute Network,内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳,如图所示。
由于CDN部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。

CDN能够缓存的一般是静态资源,如图片、文件、CSS、Script脚本、静态网页等,但是这些文件访问频度很高,将其缓存在CDN可极大改善网页的打开速度。

本博客使用的是又拍云CDN,之前完整的加载页面需要10s以上,用CDN以后几乎秒加载。

反向代理

传统代理服务器位于浏览器一侧,代理浏览器将HTTP请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站Web服务器接收HTTP请求。

和传统代理服务器可以保护浏览器安全一样,反向代理服务器也具有保护网站安全的作用,来自互联网的访问请求必须经过代理服务器,相当于在Web服务器和可能的网络攻击之间建立了一个屏障。

除了安全功能,代理服务器也可以通过配置缓存功能加速Web请求。当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器返回,加速Web请求响应速度,减轻Web服务器负载压力。事实上,有些网站会把动态内容也缓存在代理服务器上,比如维基百科及某些博客论坛网站,把热门词条、帖子、博客缓存在反向代理服务器上加速用户访问速度,当这些动态内容有变化时,通过内部通知机制通知反向代理缓存失效,反向代理会重新加载最新的动态内容再次缓存起来。

此外,反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。

代码层面

前后端分离

在如今的SpringBoot微服务项目中,前后端分离已成为业界标准使用方式,通过使用Nginx等代理方式有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多个客户展现端,例如:Web端,安卓app微信小程序等)打下坚实的基础。

数据操作

1、数组元素和对象成员访问比局部变量和字面量慢(如:var data = res.data)
2、变量会从局部作用域到全局作用域搜索过程越长越慢
3、对象嵌套(或在原型链中)越深读取越慢

DOM操作

1、减少访问或者操作DOM的次数(缓存数据到变量中,读变量比读DOM快)
2、减少回流,回流必定导致重绘,但是重绘不一定导致回流(如:多次无法避免的回流可以先让元素脱离文档流,处理完后再回归)
3、事件委托

流程控制操作

1、缓存循环次数,避免重复计算( var i = 0,len = data.length;i < len;i++ )
2、避免使用for in(使用Object.keys方法转key数组在用for遍历)
3、普通循环比函数循环(Array.forEach)快8倍
4、map表映射

脚本加载

1、script标签会阻塞页面解析渲染,所以放在body底部
2、async属性异步加载后并执行
3、defer属性异步加载并等待解析元素完成后再执行
4、如果是async、defer方法的话将script标签放在head部,便于更早加载。

资源优化

1、压缩静态资源(css,js,图片…)
2、懒加载
3、延迟加载大的组件
4、骨架屏
5、减少http请求,并将资源尽量放在同域名下,以减少DNS查询
6、不滥用cookie
7、当css文件过大的时候用critical css抽取首屏用的css优先加载
8、H5新增的rel(dns-prefetch、preconnect、prefetch、prerender、)特性
9、SSR服务器首屏渲染
10、使用静态import导入初始依赖模块。其他情况下使用动态import按需加载依赖