前端性能优化小结
什么是前端性能优化?
从用户访问资源到资源完整的展现在用户面前的过程中,通过技术手段和优化策略,缩短每个步骤的处理时间从而提升整个资源的访问和呈现速度
为什么要做前端性能优化?
在构建web站点的过程中,任何一个细节都有可能影响网站的访问速度,如果不了解性能优化知识,很多不利网站访问速度的因素会形成累加,从而严重影响网站的性能,导致网站访问速度变慢,用户体验低下
怎么做?
先来看看浏览器从发起请求到页面可以浏览会经历哪些过程:
- 浏览器的地址栏输入
URL
并按下回车 - 浏览器查找当前
URL
是否存在缓存,并比较缓存是否过期 DNS
解析URL
对应的IP
- 根据
IP
建立TCP
连接(三次握手) HTTP
发起请求- 服务器处理请求,浏览器接收
HTTP
响应 - 浏览器解析
HTML
代码,请求js,css等资源,将页面渲染出来 - 关闭
TCP
连接(4次挥手)
从上述过程中,可以分析出,优化主要分为以下几个层面
一. 解析过程的优化
- DNS解析优化(DNS缓存、减少DNS查找、keep-alive、适当的主机域名)
- 避免重定向
- 切分到多个域名
- 杜绝404
二. HTTP请求的优化
- 合理配置静态资源的长缓存与协商缓存
- cookie优化
三. 资源内容的优化
-
采用
css雪碧图
(精灵图)技术,把这些小图合并到一张大图上,使用的时候使用背景图片定位 -
最好把css或者js文件进行
合并压缩
- css,js合并成一个
- 通过一些工具(例如:webpack)把合并后的css或者js压缩成xxx.min.js,减少文件大小
- 服务器端开启资源文件的GZIP压缩
-
采用
图片懒加载
技术,在页面开始加载的时候,不请求真实的图片地址,而是默认图占位,当页面加载完成后,再根据相关的条件依次加载真实图片 -
数据的懒加载
- 开始加载页面的时候,我们只把首屏或者前两屏的数据从服务器端进行请求(有些网站首屏是服务器端渲染好,整体返回给客户端呈现的)
- 当页面下拉,滚动到哪个区域,在把这个区域需要的数据进行请求
- 采用分页技术(数据懒加载思想实现的)
-
对于不经常更新的数据,最好采用浏览器的
304缓存
(主要由服务器来处理) -
使用
字体图标
代替一些页面中的位图(图片),这样不仅做适配的时候方便,而且更加轻量级,而且减少了HTTP请求次数 -
如果在页面中出现了audio或者video标签,我们最好设置他们的
preload=none
,让在页面加载的时候,他们不进行加载preload=auto
页面加载的时候就加载音视频preload=metadata
页面加载只把音视频的头部信息进行加载
-
在客户端和服务器端进行数据通信的时候,我们尽量采用
JSON格式进行数据传输
- JSON格式的数据,能够清晰明了的站输出数据的结构,方便获取和操作
- 相比于XML,JSON更加轻量级
- 客户端和服务器端都支持JSON格式数据的处理
-
采用CDN加速
- CDN: 分布式(地域分布式)
- 效果非常好
四. 代码级别的优化
-
在编写JS代码的时候,尽量减少对DOM的操作
- DOM存在映射机制(JS中的DOM元素对象和页面的DOM结构存在映射机制),这种映射机制,是浏览器按照W3C标准完成对JS语言的构建和DOM的构建,操作DOM是同时要修改两个地方,相对于一些其它的JS编程来说是消耗性能的
- 页面中的DOM结构改变或者样式改变,会触发浏览器的回流(浏览器会把DOM结构重新进行计算,这个操作很消耗性能)和重绘(把一个元素的样式重新渲染)
-
编写代码的时候更多的使用异步编程
- 同步编程会导致: 上面的东西完不成,下面任务也做不了
-
尽可能避免一次性循环过多数据(因为循环操作是同步编程),尤其是要避免while导致的死循环
-
css选择器优化
- 尽量减少标签选择器的使用
- 尽可能少使用id选择器,多使用样式类选择器(通用性强)
- 减少选择器前面的前缀,例如:
.header .nav .left a {}
(选择器是从右向左查找的)
-
避免使用css表达式
css
.box { background-color: expression(new Date().getHours()%2 ? 'red' : 'blue') }
-
减少页面中的冗余代码,尽可能提高方法的重复使用率: '低耦合,高内聚'
-
js中避免使用
eval
- 性能消耗大
- 代码压缩后,容易出现代码执行错乱问题
-
尽量减少闭包的使用
- 闭包会形成一个不销毁的栈内存
- 还会容易导致内存的泄露
-
DOM事件绑定的时候,尽量使用
事件委托
五. webpack编译性能优化
-
升级至最新版本的 webpack,能有效提升编译性能
-
使用
dev-server / 模块热替换 (HMR)
提升开发体验- 监听文件变动忽略
node_modules
目录能有效提高监听时的编译效率
- 监听文件变动忽略
-
缩小编译范围
modules
: 指定模块路径,减少递归搜索;mainFields
: 指定入口文件描述字段,减少搜索;noParse
: 避免对非模块化文件的加载;includes/exclude
:指定搜索范围/排除不必要的搜索范围alias
: 缓存目录,避免重复寻址
-
babel-loader
- 忽略
node_moudles
,避免编译第三方库中已经被编译过的代码; - 使用
cacheDirectory
,可以缓存编译结果,避免多次重复编译
- 忽略
-
webpack-parallel-uglify-plugin
: 可多进程并发压缩 js 文件,提高压缩速度; -
第三方库模块缓存
DLLPlugin
和DLLReferencePlugin
可以提前进行打包并缓存,避免每次都重新编译;
-
使用分析
Webpack Analyse
/webpack-bundle-analyzer
对打包后的文件进行分析,寻找可优化的地方;- 配置
profile:true
,对各个编译阶段耗时进行监控,寻找耗时最多的地方;
-
source-map
- 开发:
cheap-module-eval-source-map
; - 生产:
hidden-source-map
;
- 开发:
六. 首屏加载优化方案
- Vue-Router路由懒加载(利用Webpack的代码切割)
- 使用CDN加速,将通用的库从vendor进行抽离
- Nginx的gzip压缩
- Vue异步组件
- 服务端渲染SSR
- 如果使用了一些UI库,采用按需加载
- Webpack开启gzip压缩
- 如果首屏为登录页,可以做成多入口
- Service Worker缓存文件处理
- 使用link标签的rel属性设置 prefetch(这段资源将会在未来某个导航或者功能要用到,但是本资源的下载顺序权重比较低,prefetch通常用于加速下一次导航)、preload(preload将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度)
面试思路:看候选人是否做过性能优化相关工作,可以从性能优化指标、评估工具、优化方案等角度考察。
常见的性能优化的指标
-
FCP,First Contentful Paint 首次内容绘制 web.dev/fcp/
首次内容绘制 (FCP) 指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。对于该指标,"内容"指的是文本、图像(包括背景图像)、元素或非白色的元素。
-
LCP,Largest Contentful Paint 最大内容绘制 web.dev/lcp/
-
FID,First Input Delay 首次输入延迟 web.dev/fid/
-
CLS,Cumulative Layout Shift 累积布局偏移 web.dev/cls/
-
实验性指标
-
TBT,Total Blocking Time 总阻塞时间 web.dev/tbt/
- 总阻塞时间 (TBT) 指标测量First Contentful Paint 首次内容绘制 (FCP)与Time to Interactive 可交互时间 (TTI)之间的总时间,这期间,主线程被阻塞的时间过长,无法作出输入响应。
-
TTI,Time to Interactive 可交互时间 web.dev/tti/
- TTI 指标测量页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入所需的时间。
-
性能优化评估工具
-
Chrome DevTool, developer.chrome.com/docs/devtoo...
- performance、memory
-
Lighthouse, developers.google.com/web/tools/l...
-
PageSpeed Insights, developers.google.com/speed/docs/...
-
WebpageTest www.webpagetest.org/
-
其它更多
还有其他常见优化方案
-
压缩
- 代码压缩、文本压缩、tree Shaking、Code Splitting
-
图片优化
- 小图优化:css sprite、iconfont、dataURI、svg
- 图片格式选择
- 压缩:如tinypng
-
加载策略
- 懒加载
- D NS 预解析、预加载
- 离线化Service Worker
- HTTP缓存 developer.mozilla.org/zh-CN/docs/...
- 数据缓存 LocalStorage 、Session Storagedeveloper.mozilla.org/zh-CN/docs/...
- 合并请求
- HTTP2
- 服务端渲染
-
执行渲染
- CSS代码优化:选择器、启用GPU、避免表达式
- JS代码优化
-
感官体验优化
- 骨架屏
- Snapshot
- Loading