前端性能优化主要有七种方法,包括减少请求数量、减少资源大小、优化网络连接、优化资源加载、减少重绘回流、使用性能更好的API和webpack优化
1、减少请求数量
1.1 图片处理
1.1.1 雪碧图
雪碧图是根据css sprite音译过来的,就是将很多小图标放在一张图片上就称之为雪碧图,可以减少网站http请求数量,但是当整合图片比较大的时候,一次加载比较慢,随着字体图片、svg图片的流行该技术慢慢退出了舞台
1.1.2 Base64
将图片的内容以Base64格式内嵌到HTML中,可以减少http请求数量,但是编码之后的大小比图片大了
1.1.3 使用字体图标来代替图片
1.2 减少重定向
尽量避免使用重定向,当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达之前,页面中不会呈现任何东西,也没有任何组件会被下载,降低了用户体验
如果一定要使用重定向的话,如http重定向到https,要使用301永久重定向,而不是302临时重定向,因为如果使用302则每一次访问http都会重定向到https页面,而永久重定向在第一次从http重定向到https之后,每次访问http,会直接返回https的页面
1.3 使用缓存
使用cache-control或expires这类强缓存的时候,缓存不过期的情况下不会向服务器发起请求。强缓存过期的时候,会使用last-modified或etag这类协商缓存向服务器发起请求,如果资源没有变化,则服务器返回304响应,浏览器继续从本地缓存加载资源,如果资源更新了,则服务器将更新后的资源发送到浏览器,并返回200
1.4 不使用css@import
使用css@import会造成额外的请求
1.5 避免使用空的src和href
a标签设置空的href,会重定向到当前页面的地址
form设置空的method,会提交表单到当前页面的地址
2、减少资源大小
2.1 html压缩
html代码压缩就是压缩在文本文件中有意义,但是在html中不显示的字符,包括空格,制表符
2.2 css压缩
css压缩包括无效代码删除与css语义合并
2.3 js压缩与混乱
js压缩与混乱包括无效字符及注释的删除、代码语义的缩减和优化、降低代码的可读性、实现代码的保护
2.4 图片压缩
3、优化网络连接
3.1 使用CDN
CDN是内容分发网络,它能够实时地根据网络流量和各个节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上,其目的是使用户可以就近的取得所需内容,解决网络拥挤的状况,提高网站的响应速度
3.2 使用DNS预解析
当浏览器访问一个域名的时候,需要解析一次DNS,获得对应域名的ip地址,在解析过程中,按照浏览器缓存、系统缓存、路由器换算、DNS缓存、域名服务器的顺序,逐步读取缓存,直到拿到ip地址
3.3 持久连接
使用keep-alive或者persistent来建立持久连接,降低了延时和连接建立的开销
4、优化资源加载
4.1 资源加载位置
通过优化资源加载位置,更改资源加载时机,使尽可能快地展示出页面内容,尽可能快地使用功能可用
1、css文件放在head中,先外链,后本页
2、js文件放在body底部,先外连,后本页
3、处理页面、处理页面布局的js文件放在head中,如babel-polyfill.js文件、flexible.js文件
4、body中尽量不写style标签和script标签
4.2 资源加载时机
1、异步script标签
defer:异步加载,在html解析完成后执行。defer的实际效果与将代码放在body底部类似
async:异步加载,加载完成后立即执行
2、模块按需加载
在SPA等业务比较复杂的系统中,需要根据路由来加载当前页面所需要的业务模块
按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积
webpack提供了两类技术,优先选择的方式是使用符合ECMAScript提案的import语法,第二种就是使用webpack特定的require.ensure
3、使用资源预加载preload和资源预读取prefetch
preload让浏览器提前加载指定资源,需要执行时候再执行,可以加快当前页面的加载速度
prefetch告诉浏览器加载下一个页面可能会用到的资源,可以加速下一个页面的加载速度
4、资源懒加载与资源预加载
资源延迟加载也称为资源懒加载,延迟加载资源或符合某些条件的时候才加载某些资源
资源预加载是提前加载用户所需的资源,保证良好的用户体验
资源懒加载和资源预加载都是一种错峰操作,在浏览器忙碌的时候不能操作,浏览器空闲的时候再加载资源,优化了网络性能
5、减少重绘回流
6、性能更好的API
1、用对选择器
id选择器(#myid)
类选择器(.myclassname)
标签选择器(div,h1,p)
相邻选择器(h1+p)
子选择器(ul > li)
后代选择器(li a)
通配符选择器(*)
属性选择器(a[rel=“external”])
伪类选择器(a:hover,li:nth-child)
2、使用requestAnimationFrame来替代setTimeout和setInterval
希望在每一帧开始的时候对页面进行更改,requestAnimationFrame就是告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行,使用setTimeout或者setInterval来触发更新页面的函数,该函数可能在一帧的中间或者结束的时间点上调用,进而导致该帧后面需要进行的事情没有完成,引发丢帧
3、使用IntersectionObserver来实现图片可视区域的懒加载
传统的做法中,需要使用scroll事件,并调用getBoundingClientRect方法,来实现可视区域的判断,即使使用了函数节流,也会造成页面回流。使用IntersectionObserver,则没有上述问题
7、webpack性能优化
7.1 打包公共代码
使用CommonChunkPlugin插件,将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存区中供后续使用,这回带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中抽取出来,而不是每次访问一个页面的时候,都需要去加载一个很大的文件
webpack 4 将移除 CommonsChunkPlugin, 取而代之的是两个新的配置项 optimization.splitChunks 和 optimization.runtimeChunk
通过设置 optimization.splitChunks.chunks: “all” 来启动默认的代码分割配置项
7.2 动态导入和按需加载
webpack提供了两种技术通过模块内联函数用来分离代码,优先选择的方式是ECMAScript提案的import()语法,第二种则是使用webpack特定的require.ensure
7.3 删除无用的代码
tree shaking是一个术语,通常用于移除Javascripy上下文中的未引用代码,它依赖于ES2015模块系统中的静态结构特性,例如import和export,js的tree shaking主要通过uglifyjs来完成,css的tree shaking通过purify css来实现
7.4 长缓存优化
1、将hash替换成chunkhash,这样当chunk不变的时候,缓存依然有效
2、使用Name而不是id
每个 module.id 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变
下面来使用两个插件解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建
7.4 公共代码内联
使用html-webpack-inline-chunk-plugin插件将manifest.js内联到html文件中