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
代码实现:
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的文件名
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.实现节流函数和防抖函数
函数防抖的实现:
函数节流的实现:
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库的时候,可以只引入需要用到的组件