【前端面试】优化

网页优化

网页中有大量图片加载很慢,如何优化

  1. 图片懒加载,在图片未可视区域加一个滚动条事件,检测图片是否在可视区域,如果在,将URL赋值给img标签的src进行加载
  2. 使用图片预加载技术,将当前展示的前一张和后一张优先下载(可以使用css将预加载的图片加载在屏幕外的背景上)
  3. 使用css sprite或者svg sprite

常见web性能优化

  1. 降低请求量:
    合并资源,减少HTTP请求数
    minify/gzip压缩
    webP
    lazyLoad
    图片压缩、合并(精灵图)、使用字体图表代替小图片、使用base64、图片懒加载
  2. 加快请求速度:
    预解析DNS
    减少域名数
    并行加载
    CDN分发
  3. 缓存:
    HTTP协议缓存请求
    离线缓存manifest
    离线数据缓存localStorage
  4. 渲染
    js/css优化
    加载顺序
    服务端渲染
    pipeline
    减少重排操作,例如使用transform书写动画效果,在for循环结束后再去操作dom等
  5. webpack优化
    treeShaking
    组件按需加载
    使用chunck
    模板预编译
  6. 其他
    数据懒加载、数据按需加载(上拉加载)、分页
    路由懒加载
    频繁触发的事件进项防抖和节流
    异步加载
    减少闭包、递归优化(深浅拷贝)、使用高效算法
    字库用gb2312不要utf-8,一个汉字少一个字节

CDN

CDN概念

内容分发网络(Content Delivery Network),是一种通过互联网互相连接的电脑网络系统,利用最靠近用户的服务器,更快、更可靠地将图片、音视频、应用程序已经其它文件发送给用户。从而实现传递给用户的网络内容更高的性能、更好的扩展性以及更低的成本。

典型CDN系统组成:

  • 分发服务系统

    基本工作单元是Cache设备,cache(边缘cache)负责直接响应最终用户的访问请求,把缓存在本地的内容快速地提供给用户。
    Cache还负责与源站点进行内容同步,把更新的内容以及本地没有的内容从源站点获取并保存在本地。
    衡量一个CDN系统服务能力的基本指标是:Cache设备的数量、规模、总服务能力。

  • 负载均衡系统

    负责对所有发起服务请求的用户进行访问调度,确定提供给用户的实际访问地址。
    两级调度体系分为全局负载均衡(GSLB)本地负载均衡(SLB)
    全局负载均衡(GSLB) 主要根据用户就近性原则,通过对每个服务节点进行"最优"的判断,以确定提供服务的Cache物理地址。
    本地负载均衡(SLB) 主要负责节点内部的设备负载均衡。

  • 运营管理系统

    分为运营管理和网络管理子系统,负责处理业务层面与外界系统交互所需要的收集、整理、交付工作。包含客户管理、产品管理、计费管理、统计分析等功能。

CDN作用

一般用来托管Web资源(图片、文本、脚本等)、可供下载的资源(音视频等媒体文件、软件、文档等)、应用程序(门户网站等),从而加速这些资源的访问。CDN作为基础的云服务,具有资源托管、按需扩展(应对流量高峰)等方面的优势。

  • 性能方面

    用户接收的内容由最近的数据中心发送,可以降低延迟,缩短内容加载时间;
    部分资源请求分配给CDN进行处理,可以降低服务器的负载。

  • 安全方面

    有助于防御DDos、MITM等网络攻击。

    • DDos:通过监控异常流量,限制其请求频率。
    • MITM:从原服务器到CDN节点再到ISP(Internet Service Provider),全链路使用HTTPS通信。

CDN原理

  • 用户使用CDN缓存资源

    1. 根据数据URL,经过本地DNS系统解析,如果该URL对应的是一个CDN专用的DNS服务器,DNS系统将域名解析权交给CNAME指向的CDN专用DNS服务器。
    2. CDN专用DNS服务器将CDN的全局负载均衡设备IP返回给用户。
    3. 用户向CDN的全局负载均衡设备发送数据请求。
    4. CDN的全局负载均衡设备根据用户IP以及用户请求的URL,选择一台用户所属区域的区域负载均衡设备,告诉用户设备IP,让用户向这台设备发送请求。
    5. 区域负载均衡选择一台合适的缓存服务器来提供服务,将缓存服务器的IP返回给全局负载均衡设备。
    6. 全局负载均衡设备把服务器IP返回给用户
    7. 用户向对应的缓存服务器发送请求,缓存服务器响应服务,将内容发送到用户终端。

    若缓存服务器没有用户需要的内容,缓存服务器向它的上一级缓存服务器请求内容,直到获取需要的内容,若最终未找到,会回到自己的服务器获取内容。
    在这里插入图片描述

  • 用户未使用CDN缓存资源

    1. 浏览器通过DNS对域名进行解析,依次得到域名对应的IP地址
    2. 浏览器根据IP地址,向域名服务器主机发送数据请求
    3. 服务器向浏览器返回响应数据

CDN使用场景

  • 进行静态资源的缓存
    将网站的静态资源,例如css、图片、js脚本等,放在CDN上,也可以将整个项目放在CDN上,完成一键部署。
  • 使用第三方CDN服务
    开源项目,可以使用第三方的CDN服务
  • 直播传送流媒体
    直播本质上时使用流媒体传送,CDN支持流媒体传送,所以直播可以通过使用CDN来提高访问速度。
    CDN在处理流媒体时,与普通静态文件不同,普通文件边缘节点没找到的话,回去上一层接着寻找,但是由于流媒体本身数据量非常大,如果使用回源的方式,会带来性能问题,所以流媒体一般采用主动推送的方式。

懒加载

懒加载又叫按需加载或者延迟加载,是指在长网页中延迟加载图片数据,是一种较好的网页性能优化方式。
在长网页或应用中,如果图片比较多,这种情况下,所有的图片都加载,但是用户只看到可视区域内的那一部分图片数据,这样就浪费了性能。图片懒加载可以很好的解决上述问题。滚动屏幕之前,可视区域外的图片不会加载,当屏幕滚动,当图片进入可是区域后,才加载,这样就可以提高网页的加载速度,也降低服务器的负载。

特点:

  • 减少无用资源的加载
    使用懒加载可以很明显的降低服务器的压力和流量,同时也减少浏览器的负担。
  • 提升用户体验
    如果同时加载很多图片,可能需要长时间的等待,会影响用户体验。而使用懒加载,就可以大大提高用户体验。
  • 防止加载过多图片,影响其他资源文件的加载

原理:
当将图片的src属性复制后,就会请求图片资源,然后加载图片。那么就可以使用HTML5的data-xxx属性来存储图片路径,当需要加载图片的适合,将data-xxx内存储的图片路径赋值给图片的src,就实现了懒加载。

例子:
在这里插入图片描述

<div class="imgContainer">
	<img src="1.jpg" data-src="1.jpg" data-set="true" />
	<img src="loading.gif" data-src="2.jpg" />
	<img src="loading.gif" data-src="3.jpg" />
	<img src="loading.gif" data-src="4.jpg" />
	<img src="loading.gif" data-src="5.jpg" />
	<img src="loading.gif" data-src="6.jpg" />
	<img src="loading.gif" data-src="7.jpg" />
</div>
<script>
	const images = document.querySelectAll('img');
	function lazyLoad() {
		const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; // 浏览器滚动过的距离
		const winHeight = window.innerHeight; // 浏览器可视区域高度

		for (let i = 0; i < images.length; i++) {
			const img = images[i];
			
			if (img.offsetTop < scrollTop + winHeight) {
				if (img.getAttribute('data-set') === 'true') {
					continue;
				}
				img.src = img.getAttribute('data-src');
				img.data-set = 'true';
			}
		}
	}

	window.onscroll = lazyLoad();
</script>

懒加载和预加载的区别
预加载时提前加载,懒加载是延迟加载或不加载。两种方式都是提高网页性能的方式。

  • 懒加载

    又叫延迟加载,是指在长网页中延迟加载图片,当用户需要访问时,再去加载,可以提高首屏加载速度,提升用户体验,也可以降低服务器压力。
    适用于长页面并且图片很多的网站。
    实现原理是,将图片的src属性设置为空,即不加载图片,并且把真实路径存在图片的某个属性中,当页面滚动时,判断图片是否进入页面的可视区域,进入则在存放图片真实路径的属性中取出路径,并赋值给图片的src属性,这样就可以实现图片的懒加载。

  • 预加载

    指的是将需要加载的资源,提前请求加载到本地,这样当需要使用时,就直接从缓存中取预加载的资源。
    通过预加载可以减少用户等待的时间,从而提高用户体验。
    例如,使用image对象,为image对象设置src属性;或者将图片提前加载在可视区域外;提前载入图片,使用css隐藏预加载的图片,等方法来实现图片的预加载。

回流和重绘

  • 回流也叫重排(Reflow)

    当元素因为规模尺寸、布局、隐藏等改变,需要重新渲染部分或者全部文档时则称为回流。

    导致回流的操作:

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

    一些元素需要更新属性,而这些属性只影响元素的外观、风格,而不会影响布局则叫重绘。重绘不一定回流,但是回流一定重绘。

    导致重绘的操作:

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

如何避免回流和重绘

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

渲染队列机制
浏览器会将所有回流、重绘的操作放在一个队列中,当队列的操作到了一定的数量或者时间间隔,浏览器就会对对流进行批处理。
这样的好处就是,可以让多次回流、重绘变成一次回流重绘。
例如上述中读操作放一起,会等待所有读操作进入队列之后,一起执行,这样原本要触发多次回流就变成了触发一次回流。

动画优化
动画会频繁的操作DOM,这样可能会导致页面的性能问题。
可以通过将动画的position属性设置为absolute或者fixed,将动画脱离文档流,这样动画的回流就不会影响到页面了。

documentFragment

MDN:
DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的Document使用,就像标准的而document一样,存储由节点(nodes)组成的文档结构。与document相比,最大的区别是DocumentFragment不是真实DOM树的一部分,它的变化不会触发DOM树的重新渲染,且不会导致性能等问题。

当把DocumentFragment节点插入文档树时,插入的不是DocumentFragment自身,而是它所有的子孙节点。
当需要频繁的操作DOM时,可以将DOM元素插入DocumentFragment中,所有DOM操作结束后,一次性将DocumentFragment的子孙节点插入文档中。
DocumentFragment节点插入DOM树,不会触发页面的重绘,可以大大提高页面性能。

防抖和节流

防抖

指在事件被触发n秒后再执行回调,如果在n秒内,事件再次触发,重新计时。

应用场景:

  • 表单按钮提交:防止重复提交,只执行最后一次
  • 需要发送请求的验证场景:例如表单验证需要向服务端发送请求,当连续输入事件一定时间间隔内的最后一次完成后,再向服务端进行请求;还有搜索联想词功能等。

可以使用lodash中的lodash.debounce方法

实现

function debounce(fn, wait) {
	let timer = null;

	return function() {
		const context = this;
		const args = [...arguments];

		if (timer) {
			clearTimeout(timer);
			timer = null;
		}

		timer = setTimeout(() => {
			fn.apply(context, args);
		}, wait);
	}
}

节流

指规定的单位时间内,只能有一次触发事件的回调函数执行,如果同一个单位时间内,事件被多次触发,只生效一次。

应用场景:

  • 拖拽:固定事件内只执行一次,防止高频次触发位置变动
  • 缩放(浏览器resize)
  • scroll
  • 动画:避免短时间高频率触发动画引起性能问题

实现

// 时间戳
function throttle(fn, delay) {
	let preTime = Date.now();

	return function() {
		const context = this;
		const args = [...arguments];
		const nowTime = Date.now();
		
		if (nowTime - preTime >= delay) {
			preTime = Date.now();
			
			return fn.apply(context, args);
		}
	}
}

// 定时器
function throttle(fn, wait) {
	let timer = null;

	return function() {
		const context = this;
		const args = [...arguments];

		if (!timer) {
			timer = setTimeout(() => {
				fn.apply(context, args);
				timer = null;
			}, wait);
		}	
	}
}

图片优化

优化手段:

  • 减少使用图片。修饰图片可以用css代替。
  • CDN加载,根据适配的屏幕宽度,请求裁剪好的图片。
  • 小图像使用base64格式
  • 精灵图:多个图标图片整合到一个图片中
  • 选择正确的图片格式
    1. 能够显示WebP格式的浏览器尽量使用WebP格式(更好的图像数据压缩算法带来更小的图片体积,但是兼容性差)。
    2. 小图使用PNG,类似图标图篇,用SVG代替。
    3. 照片尽可能使用JPEG。

图片格式对应的使用场景:

  1. BMP
    无损、支持索引色也支持直接色的点阵图。
    这种格式基本上没有对数据进行压缩,所以BMP格式的图片通常是较大的文件。
  2. JPEG
    有损、采用直接色的点阵图。
    JPEG格式的图片优点是采用了直接色,得益于更丰富的色彩,JPEG非常适合存储照片。
    但是与GIF相比,JPEG不适合存储线框类、logo类的图,有损压缩会降低图片的清晰度,导致图片模糊。
  3. PNG-8
    无损、使用索引色的点阵图,是非常好的GIF格式替代者。
    所以尽可能使用PNG-8替代GIF,相同图片效果下,PNG-8体积更小,并且支持透明度的调节。
  4. PNG-24
    无损、使用直接色的点阵图。
    PNG-24的优点在于它压缩了图片数据,同样效果的图片, PNG-24格式比BMP文件要小的多。但是 PNG-24的图片要比JPEG、GIF、PNG-8大的多。
  5. GIF
    无损、采用索引色的点阵图。
    采用LZW压缩算法进行编码。
    优点:文件小、支持动画、透明
    缺点:仅支持8bit的索引色,对色彩要求高的场景不友好
    GIF适用于对色彩要求不高同时需要文件体积较小的场景。
  6. SVG
    无损矢量图。由直线、曲线以及绘制它们的方法组成。放大SVG图片,不会失真,看到的线和曲线,不会出现像素点。
    适合绘制Logo和Icon。例如iconfont就支持svg格式的icon输出。
  7. WebP
    谷歌开发,支持无损以及有损压缩、使用直接色的点阵图。
    与其他格式相比,相同质量的图片,WebP格式的图片文件体积更小。但是兼容性差,目前仅Chrome和Opera支持。
    • 无损压缩,相同质量的WebP图片,文件比PNG小26%
    • 有损压缩,相同质量的WebP图片,文件比PNG小25%-34%
    • WebP格式支持图片透明度,一个无损压缩的WebP格式图片,如果需要支持透明度,仅需要22%的额外文件大小

webpack优化

提高webpack打包速度

  1. loader优化
    对于loader,最影响打包速度的可能是Babel,Babel需要将代码转为字符串生成AST,然后对AST继续进行转变,最后生成新代码。项目越大,转换的代码量越大,速度越慢

    优化

  • 优化文件搜索范围

    module.exports = {
    	module: {
    		rules: [
    			{
    				test: /\.js$/, // 规定js文件使用babel
    				loader: 'babel-loader',
    				include: [resolve('src')], // 规定在src目录下查找需要babel编译的文件
    				exclude: /node_modules/ // 排除不查找的路径
    			}
    		]
    	}
    }
    	```
    
    
  • 缓存babel编译过的文件

    loader: 'babel-loader?cacheDirectory=true'
    
  1. HappyPack
    Node是单线程运行的,所以Webpack打包过程也是单线程的,特别是在执行loader的时候,长时间编译的任务很多,会导致等待的情况。
    HappyPack可以将Loader的同步执行转换为并行,这样就可以利用系统资源来加快打包速度。

    module: {
    	loaders: [
    		{
    			test: /\.js$/,
    			include: [resolve('src')],
    			exclude: /node_modules/,
    			loader: 'happypack/loader?id=happybabel' // id对应plugins中HappyPack配置中的id
    		}
    	],
    	plugins: [
    		new HappyPack({
    			id: 'happybabel',
    			loaders: ['babel-loader?cacheDirectory=true'],
    			threads: 4 // 开启4个线程
    		})
    	]
    }
    
  2. DllPlugin
    可以将特定的类库提前打包然后引入。
    可以极大的减少打包类库的次数,只有当类库更新版本才有需要重新打包,并且也实现了将公共代码抽离称单独文件的优化方案。

    // 需要单独配置在一个文件中 webpack.dll.conf.js
    const path = require('path');
    const webpack = require('webpack');
    
    module.exports = {
    	entry: {
    		vendor: ['react'] // 需要统一打包的类库
    	},
    	output: {
    		path: path.join(__dirname, 'dist'),
    		filename: '[name].dll.js',
    		library: '[name]-[hash]'
    	},
    	plugins: [
    		new webpack.DllPlugin({
    			// name需要和output.library一致
    			name: '[name]-[hash]',
    			// 需要与webpack配置中DllReferencePlugin一致
    			context: __dirname,
    			path: path.join(__dirname, 'dist', '[name]-manifest.json')
    		})
    	]
    }
    
    // webpack.conf.js
    module.exports = {
    	plugins: [
    		new webpack.DllReferencePlugin({
    			context: __dirname,
    			// manifest就是之前打包出来的json文件
    			manifest: require('./dist/vendor-manifest.json')
    		})
    	]
    }
    
  3. 代码压缩
    Webpack3中,一般使用uglifyJS来压缩代码,但是单线程运行的,为了加速速度,可以使用webpack-parallel-uglify-plugin来运行UglifyJS,从而提高速度。
    在Webpack4中,不要上述操作了,只需要将mode设置为production就可以默认开启上述功能。

    对于代码压缩,是必须做的性能优化,当然除了压缩js代码之外,还可以压缩html、css代码以及通过配置项删除console.log等无用代码。

  4. 其他

    • resolve.extensions
      表明文件后缀列表,默认查找顺序是[‘.js’, ‘.json’],如果导入文件有添加后缀,就会按照这个顺序查找文件,尽可能减少后缀列表长度,并将出现频率高的后缀排在前面。
    • resolve.alias
      通过别名的方式来映射一个路径,能让Webpack更快找到路径
    • module.noParse
      如果确定文件下没有其他依赖,可以使用该属性让Webpack不搜秒该文件,对大型类库有帮助

减少webpack打包体积

  1. 按需加载

    对于SPA项目,可以使用按需加载,将每个路由页面单独打包为一个文件。

  2. Scope Hoisting

    Scope Hoisting可以分析出模块之间的依赖关系,尽可能的把打包出来的模块合并到一个函数中去。

    例如:两个文件打包

    // test.js
    export const a = 1;
    // index.js 
    import { a } from './test.js';
    
    // 打包后的代码
    [
    	/* 0 */
    	function (module, exports, require) {
    		// ... test.js
    	}
    	/* 1 */
    	function (module, exports, require) {
    		// ... index.js
    	}
    ]
    
    // 使用Scope Hoisting, 代码就会尽可能合并到一个函数中去
    [
    	/* 0 */
    	function (module, exports, require) {
    		// ... test.js
    		// ... index.js
    	}
    ]
    

    使用Scope Hoisting后生成的代码明显比使用之前要少。
    Webpack4中如果开启功能:

    module.exports = {
    	optimization: {
    		concatenateModules: true
    	}
    }
    
  3. Tree Shaking

    用来删除项目中未引用的代码

    // test.js
    export const a = 1;
    export const b = 2; // 未使用
    
    // index.js
    import { a } from './test.js';
    

    Webpack4, 开启生产环境就会自动启动该优化功能。

webpack优化前端性能

指优化webpack的输出结果,让打包的结果在浏览器运行更快速高效。

  • 压缩代码

    删除多余的代码、注释、简化代码写法等方式。
    可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩js文件,利用cssnano(css-loader?minimize)来压缩css

  • 利用CDN加速

    构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对output参数和各loader的publicPath参数来修改资源路径

  • Tree Shaking

    讲代码中无用的片段删除,可以通过在启动webpack时追加参数->optimize-minimize来实现

  • Code Splitting

    将代码按路由维度或者组件分块(chunk)。
    这样可以做到按需加载,同时可以充分利用浏览器缓存。

  • 提取公共第三方库

    SplitChunksPlugin插件来进行公共模块抽取,利用浏览器缓存可以长期缓存这些无需频繁变动的公共代码。

提高webpack的构建速度

  1. 多入口,使用CommonsChunkPlugin来提取公共代码
  2. 通过externals配置来提取常用库
  3. 利用DllPlugin和DllReferencePlugin预编译资源模块,通过DllPlugin来对那些引用但是不会修改的npm包进行预编译,再通过DllReferencePlugin将预编译的模块加载进来。
  4. 使用Happypack实现多线程加速编译
  5. 使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。原理上webpack-uglify-parallel采用了多核并行压缩来提升压缩速度。
  6. 使用Tree-shaking和Scope Hoisting来剔除多余代码。

内存泄露如何检查

使用Chrome DevTools

使用性能分析器可视化内存消耗

以下面的代码为例,有两个按钮,添加和移除。
点击添加按钮,通过创建dom节点,将1-10000的数字显示到dom节点中。
点击清除按钮,清除全部由添加按钮事件创建的所有dom节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="addDom()">添加</button>
    <button onclick="removeDom()">清除</button>
    <div id="container"></div>
    <script>
        let domArray = [];
        const container = document.getElementById('container');


        function addDom() {
            for (let i = 0; i < 10000; i++) {
                const dom = document.createElement('div');
                dom.innerHTML = i;
                container.appendChild(dom);
                domArray.push(dom);
            }
        }

        function removeDom() {
            // for (let dom of domArray) {
            //     container.removeChild(dom);
            // }
            container.innerHTML = 'cleared';
            domArray = [];
        }
    </script>
</body>
</html>

点击添加按钮,JS Heap会出现蓝色的峰值,这是因为JavaScript正在创建DOM节点并将创建的dom添加到domArray数组中。并且绿色的Nodes(dom)数量也在增加。在这里插入图片描述点击清除按钮,JS Heap和Nodes只有在操作container.innerHTML = 'cleared';时有一次上升,因为清除操作并没有移除dom节点,只是操作了container节点。
在这里插入图片描述
如果在实际的项目中,观察到内存持续出现峰值,并且内存消耗一直不会下降,那可能存在内存泄露。

识别分离的DOM节点

分离的DOM节点是指一个节点从DOM树中移除,但可能存在引用该dom的情况。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="addDom()">添加</button>
    <button onclick="removeDom()">清除</button>
    <div id="container"></div>
    <script>
        let dom;
        const container = document.getElementById('container');

        function addDom() {
            dom = document.createElement('div');
            dom.innerHTML = '1231231321';
            container.appendChild(dom);
        }

        function removeDom() {
            container.removeChild(dom);
        }
    </script>
</body>
</html>

使用heap snapshot可以检查分离的DOM节点

在这里插入图片描述

点击页面按钮后,点击下面蓝色的Take snapshot按钮,可以搜索输入Detached来过滤结果中的分离的dom节点

在这里插入图片描述

web前端性能优化ing

性能优化概念

起因

当某个功能没有满足其需求的可选方案时,用户需要忍受糟糕的体验,这个时候就存在对产品进行优化和改进的空间。
比如某个网站加载速度更快,对用户操作的响应速度更快,都会影响网站的转换率、留存率等。

性能的影响

  1. 用户留存率

    网站的一系列经济转换是建立在用户留存率上的,比如社交网站希望用户间的互动,电商网站希望用户浏览、购买商品,等等。
    用户的留存率 = 用户登录注册之日后一段时间后,仍在使用网站的用户数 / 总注册用户数。
    该指标对网站的运行有重要的指导意义,而网页加载时间很大程度上影响着该指标,当然影响该指标的因素还有很多。
    通过优化性能来提高留存率是必要措施。

  2. 网站转化率

    网站转化率 = 用户目标行为的访问次数 / 用户访问总次数。
    例如,电商网站上某个商品,用户购买量 / 用户浏览量,该比率可以大概得到用户作为访客到消费者的转化率。

  3. 用户体验和传播

    当前环境下,用户通过移动设备访问网站,会产生流量数据,当网站存在冗余数据、大资源文件等问题时,就会造成网络资费的浪费以及加载时间增加等问题,降低用户体验。当然低用户体验的应用,在使用过程中,口碑会下降,不利于应用的传播。

性能评估模型

原则时以用户为中心,然后根据该原则引出知道性能优化的策略。参照RAIL性能模型。
RAIL 是 response (响应)、 animation(动画)、idle(浏览器空置状态)和 load(加载)。
在这里插入图片描述

  1. response

    对于用户的操作,比如点击表单提交,如果没有在合理的时窗内完成响应,也就是说采取动作和得到响应之间出现了断层,用户就会感知延迟。

    例如输入、点击、表单提交、动画等操作,当反馈时间窗口超过100ms,用户就会感知延迟。

    响应的主要交互是:

    • 在首次收到操作时,在100毫秒内得到回应
    • 理想情况是得到最终响应结果,如果需要花更长的时间进行处理,需要给用户还在处理中的提示,例如loading效果。
  2. animation

    动画主要包含以下交互效果:
    - 视觉动画
    - 滚动
    - 拖拽

    因为人的视觉神经是有反应速度的,是1/24s,即物体移出后,物体不会在眼中立即消失,而会延续存在1/24s的时间。也就是说,无论动画帧率有多高,人眼只能分辨其中的30帧,但是越高的帧率就会带来更好的流畅体验,因此动画要尽可能达到60fps的帧率(一帧图像的生成预算为16.67ms, 1000ms/60,除去浏览器绘制时间,留给代码执行的时间仅为10ms左右)。

  3. idle

    要想响应较为精美的动画,通常都需要较长的处理时间

  4. load

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值