性能优化部分

124 阅读11分钟

1.懒加载的概念

懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能

如果使用图片的懒加载就可以解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在滚动屏幕时才加载。这样使得网页的加载速度更快,减少了服务器的负载。懒加载适用于图片较多,页面列表较长(长列表)的场景中

2.懒加载的特点

减少无用资源的加载:使用懒加载明显减少了服务器的压力和流量,同时也减小了浏览器的负担

提升用户体验:如果同时加载较多图片,可能需要等待的时间较长,这样影响了用户体验,而使用懒加载就能大大的提高用户体验

防止加载过多图片而影响其他资源文件的加载:会影响网站应用的正常使用

3.懒加载的实现原理

图片的加载是由src引起的,当对src赋值时,浏览器就会请求图片资源。根据这个原理,我们使用HTML5的data-xxx属性来储存图片的路径,在需要加载图片的时候,将data-xxx中图片的路径赋值给src,这样就实现了图片的按需加载,即懒加载(注意:data-xxx中的xxx可以自定义,这里我们使用data-src来定义)

懒加载的实现重点在于确定用户需要加载哪张图片,在浏览器中,可视区域内的资源就是用户需要的资源。所以当图片出现在可视区域时,获取图片的真实地址并赋值给图片即可

使用原生JavaScript实现懒加载:

window.innerHeight是浏览器可视区的高度

要获取当前页面的滚动条纵坐标位置,用:document.documentElement.scrollTop;而不是document.body.scrollTop;(documentElement对应的是 html 标签,而body对应的是 body 标签)

imgs.offsetTop是元素顶部距离文档顶部的高度(包括滚动条的距离)

图片加载条件:img.offsetTop < window.innerHeight + document.body.scrollTop

image.png

代码实现:

image.png

image.png

image.png

4.vue组件懒加载

1.ES6推荐方式imprort ()----推荐使用

// 官网可知:下面没有指定webpackChunkName,每个组件打包成一个js文件。

const Foo = () => import('../components/Foo')

const Aoo = () => import('../components/Aoo')

// 下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。

const Foo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/Foo')

const Aoo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/Aoo')

2.使用vue异步组件resolve

这一种方法比较常见。它主要是使用了resolve的异步机制,用require代替了import,实现按需加载,下面是代码示例

//const 组件名 = resolve => require([‘组件路径’],resolve)

//(这种情况下一个组件生成一个js文件)

const home = resolve => require(['../view/home'],resolve)

3.webpack提供的require.ensure()实现懒加载

  • 这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
  • require.ensure可实现按需加载资源,包括js,css等。他会给里面require的文件单独打包,不会和主文件 打包在一起。
  • 第一个参数是数组,表明第二个参数里需要依赖的模块,这些会提前加载。
  • 第二个是回调函数,在这个回调函数里面require的文件会被单独打包成一个chunk,不会和主文件打包在一 起,这样就生成了两个chunk,第一次加载时只加载主文件。
  • 第三个参数是错误回调。
  • 第四个参数是单独打包的chunk的文件名

image.png

5.回流与重绘的概念及触发条件

(1)回流:当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流,下面这些操作会导致回流:

  • 页面的首次渲染
  • 浏览器的窗口大小发生变化
  • 元素的内容发生变化
  • 元素的尺寸或者位置发生变化
  • 元素的字体大小发生变化
  • 激活CSS伪类
  • 查询某些属性或者调用某些方法
  • 添加或者删除可见的DOM元素

在触发回流(重排)的时候,由于浏览器渲染页面是基于流式布局的,所以当触发回流时,会导致周围的DOM元素重新排列,它的影响范围有两种:

全局范围:从根节点开始,对整个渲染树进行重新布局

局部范围:对渲染树的某部分或者一个渲染对象进行重新布局

(2)重绘:当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘,下面这些操作会导致重绘:

  • color、background相关属性:background-color、background-image等
  • outline相关属性:outline-color、outline-width、text-decoration
  • border-radius、visibility、box-shadow

注意:当触发回流时,一定会触发重绘,但是重绘不一定会引发回流

6.如何避免回流与重绘?

  • 操作DOM时,尽量在低层级的DOM节点进行操作
  • 不要使用table布局,一个小的改动可能会使整个table进行重新布局
  • 使用CSS的表达式
  • 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式
  • 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
  • 避免频繁操作DOM,可以创建一个文档片段documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中
  • 将元素先设置display:none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘
  • 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制

浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列

浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘

7.对节流与防抖的理解

函数防抖是指在事件被触发n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求

防抖的原理就是:当执⾏⼀个事件函数时,会等待⼀个阈 (yu) 值,可以设置为 n 秒,只 有在 n 秒之后不再有操作,事件才会真正被触发。这样就不会引起⻚⾯抖动

防抖函数的应用场景:

  • 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
  • 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤ lodash.debounce
  • 场景:input验证、搜索联想、resize

函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在scroll函数的事件监听上,通过事件节流来降低事件调用的频率

节流函数的适⽤场景:

  • 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
  • 缩放场景:监控浏览器resize
  • 动画场景:避免短时间内多次触发动画引起性能问题
  • 场景:按钮点击、下拉加载、鼠标滚动、拖拽动画(节流通常用在比防抖刷新更频繁的场景下,而且大部分是需要涉及动画的操作。)

8.实现节流函数和防抖函数

函数防抖的实现:

image.png

image.png

函数节流的实现:

image.png

image.png

9.如何对项目中的图片进行优化?

  • 不用图片:很多时候会使用到很多修饰类图片,其实这类修饰图片完全可以用CSS去代替
  • 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用CDN加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片
  • 小图使用base64格式
  • 将多个图标文件整合到一张图片中(雪碧图)
  • 选择正确的图片格式:对于能够显示WebP格式的浏览器尽量使用WebP格式。因为WebP格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好;小图使用PNG,其实对于大部分图标这类图片,完全可以使用SVG代替;照片使用JPEG

10.如何⽤webpack来优化前端性能?

⽤webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运⾏快速⾼效

  • 压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。可以利⽤webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩 JS⽂件,利⽤cssnano(css-loader?minimize)来压缩css
  • 利⽤CDN加速:在构建过程中,将引⽤的静态资源路径修改为CDN上对应的路径。可以利⽤webpack对于output参数和各loader的 publicPath参数来修改资源路径
  • TreeShaking:将代码中永远不会⾛到的⽚段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现
  • Code Splitting:将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利用浏览器缓存
  • 提取公共第三⽅库: SplitChunksPlugin插件来进⾏公共模块抽取,利用浏览器缓存可以⻓期缓存这些⽆需频繁变动的公共代码

11.Vue性能优化

源码优化:

代码模块化,可以把很多常用的地方封装成单独的组件,在需要用到的地方引用,而不是写过多重复的代码,每一个组件都要明确含义,复用性越高越好,可配置型越强越好,包括css也可以通过less和sass的自定义css变量来减少重复代码

for循环设置key值,在用v-for进行数据遍历渲染的时候,为每一项都设置唯一的key值,为了让Vue内部核心代码能更快地找到该条数据,当旧值和新值去对比的时候,可以更快的定位到diff

Vue路由设置成懒加载,当首屏渲染的时候,能够加快渲染速度

更加理解Vue的生命周期,不要造成内部泄漏,使用过后的全局变量在组件销毁后重新置为null

使用keep-alive,keep-alive是Vue提供的一个比较抽象的组件,用来对组件进行缓存,从而节省性能

打包优化:

修改vue.config.js中的配置项,把productionSourceMap设置为false,不然最终打包过后会生成一些map文件,如果不关掉,生成环境是可以通过map去查看源码的,并且可以开启gzip压缩,使打包过后体积变小

使用cdn的方式外部加载一些资源,比如vue-router、axios等Vue的周边插件,在webpack.config.js里面,externals里面设置一些不必要打包的外部引用模块。然后在入门文件index.html里面通过cdn的方式去引入需要的插件

减少图片使用,因为对于网页来说,图片会占用很大一部分体积,所以,优化图片的操作可以有效的来加快加载速度。可以用一些css3的效果来代替图片效果,或者使用雪碧图来减少图片的体积

按需引入,咱们使用的一些第三方库可以通过按需引入的方式加载。避免引入不需要使用的部分,无端增加项目体积。比如在使用element-ui库的时候,可以只引入需要用到的组件