前端性能优化

# 加载性能优化

本质:

    1、减少请求次数;

    2、减少请求资源的大小;

    3、网络优化;

## 1、减少请求次数

## 为什么减少请求次数?

### 浏览器能够并行发出请求,但是每次并行发出请求的个数是有限制的,以chrome为例:

#### 同一域名下,同一GET请求的并发数是1,也就是说上一个请求结束,才会执行下一个请求,否则置入队列等待发送;

#### 同一域名下,不同GET/POST请求的并发数量是6。当发送的请求数量达到6个,并且都没有得到响应时,后面的请求会置入队列等待发送。

所以资源请求数过多肯定比请求数少更耗时,直接影响网页的加载速度;

### 减少请求次数方式

#### 1)图片资源

    CSS雪碧图技术

        把一些常用、重复使用的小图合并成一张大图,使用的时候通过背景图片定位(background-position),定位到具体的某一张小图上;

        1、UI给图;

        2、webpack插件:webpack-spritesmith

    图片懒加载

            视区外图片先不加载,当进入视区或者进入视区之前的某个位置加载;

            1、css的loading属性;

            2、getBoundingClientRect方法,获取dom元素的top、left、bottom、right、height、width信息,对比视区大小,进行图片加载(需要结合节流);

            3、IntersectionOberser方法,能够监听元素是否到达当前视口的事件;

        字体图标

            一个图标字体比一系列图像要小,一旦图标字体加载了,图标就会马上渲染出来,不需要下载一个图像,可以减少HTTP请求。

        base64编码

            图片的base64编码就是可以将一张图片数据编码成一串字符串,使用该字符串代替图像地址url;

            (均衡css体积增大和http请求减少之间的收益)

#### 2)合理利用缓存

        浏览器缓存(资源)

            强缓存

            协商缓存

        DNS缓存(DNS查找时间)

        分包加载 (Bundle Spliting)

            避免一行代码修改导致整个 bundle 的缓存失效

#### 3)合并CSS和JS文件

        将CSS和JavaScript文件合并为单独的文件。合并CSS和JavaScript文件是减少HTTP请求数量和提高网站加载速度的有效方法;

## 2、减少资源大小

相同网络环境下,更小体积意味着传输速度更快;

### 减少资源大小方式

#### 1)资源压缩

        js、css、html资源压缩

                gzip压缩:nginx配置中可以开启,资源传输体积压缩变小,相应会增加服务器压缩和浏览器资源解压的压力;对于图片资源压缩效率不明显;

                Terser 等工具是 Javascript 资源压缩混淆的神器。对代码层进行处理,比如:

                    1、长变量名替换短变量;

                    2、删除空格换行符;

                    3、预计算能力;

                    4、移除无法被执行的代码;

                    5、移除无用的变量及函数

        图片资源压缩

                图片压缩工具:tinyPng等

                图片格式:,webp 普遍比 jpeg/png 更小,而 avif 又比 webp 小一个级别

                    如何鉴别浏览器是否支持webp?

                        通过canvas来判断(这个比较常用),创建一个canvas元素,然后把它转成image/webp格式的data_url,如果这个data_url里面包含webp,则代表当前浏览器支持webp格式, 反之则不支持:document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp')

                        在服务端根据请求header信息判断浏览器是否支持webp:在图片请求发出的时候,Request Headers 里有 Accept,服务端可以根据Accept 里面是否有 image/webp 进行判断。

                        通过加载一张 webp 图片进行判断:先加载一个WebP图片,如果能获取到图片的宽度和高度,就说明是支持WebP的;

#### 2)Tree Shaking技术

        Tree Shaking: 无用导出将在生产环境进行删除,到达减少资源体积的效果;

## 3、网络优化

### 1)CND:就近原则

### 2)Http2.0

        多路复用,在浏览器可并行发送 N 条请求。

        首部压缩,更小的负载体积。

        请求优先级,更快的关键请求

## 其他

    路由懒加载

    第三方组件按需加载

# 渲染性能优化

## 浏览器渲染过程

>   解析HTML生成DOM树。

>   解析CSS生成CSSOM规则树。

>   解析JS,操作 DOM 树和 CSSOM 规则树。

>   将DOM树与CSSOM规则树合并在一起生成渲染树。

>   遍历渲染树开始布局,计算每个节点的位置大小信息。

>   浏览器将所有图层的数据发送给GPU,GPU将图层合成并显示在屏幕上。

## 重排

+ 当改变 DOM 元素位置或大小时,会导致浏览器重新生成渲染树,这个过程叫重排。

## 重绘

+ 当重新生成渲染树后,就要将渲染树每个节点绘制到屏幕,这个过程叫重绘。

+ 不是所有的动作都会导致重排,例如改变字体颜色,只会导致重绘。

+ 重排和重绘这两个操作代价非常大,因为 JavaScript 引擎线程与 GUI 渲染线程是互斥,它们同时只能一个在工作,因此重排和重绘会阻塞主线程。

## 渲染性能优化方式

### 1)资源加载优先级控制

+   preload/prefetch

-       preload/prefetch 可控制 HTTP 请求优先级,从而达到关键请求更快响应的目的;

-           preload 加载当前路由必需资源,优先级高,一般对于 Bundle资源使用preload;

-           refetch 优先级低,在浏览器 idle 状态时加载资源,一般用以加载非首页资源;

        dns-prefetch,可对主机地址的 DNS 进行预解析。

+   js和css的引入位置/script类型设置

-       css引入放在head便签尾部,script脚本防砸body标签尾部;

-       脚本与DOM/其它脚本的依赖关系很强:对<script>设置defer

-       脚本与DOM/其它脚本的依赖关系不强:对<script>设置async

### 2)减少重排重绘

        减少页面DOM操作;

        对 DOM 元素执行一系列操作,可以将 DOM 元素脱离文档流,修改完成后,再将它带回文档。例如:隐藏元素(display:none)、文档碎片(DocumentFragement)等(虚拟dom);

        用 JavaScript 修改样式时,最好不要直接修改单个样式属性,而是替换 class 来改变样式;

        合理使用防抖和节流;

### 3)利用缓存

        页面缓存(keep-alive),接口缓存(减少数据更新导致的页面刷新)

### 4)Web Worker

        用于那些处理纯数据,或者与浏览器 UI 无关的长时间运行脚本;

#Webpack优化

 1.提升开发体验
  • 使用 Source Map 让开发或上线时代码报错能有更加准确的错误提示
 2.提升 webpack 提升打包构建速度
  • 使用 HotModuleReplacement 让开发时只重新编译打包更新变化了的代码,不变的代码使用缓存,从而使更新速度更快。
  • 使用 OneOf 让资源文件一旦被某个 loader 处理了,就不会继续遍历了,打包速度更快。
  • 使用 Include/Exclude 排除或只检测某些文件,处理的文件更少,速度更快。
  • 使用 Cache 对 eslint 和 babel 处理的结果进行缓存,让第二次打包速度更快。
  • 使用 Thead 多进程处理 eslint 和 babel 任务,速度更快。(需要注意的是,进程启动通信都有开销的,要在比较多代码处理时使用才有效果)
 3.减少代码体积
  • 使用 Tree Shaking 剔除了没有使用的多余代码,让代码体积更小。
  • 使用 @babel/plugin-transform-runtime 插件对 babel 进行处理,让辅助代码从中引入,而不是每个文件都生成辅助代码,从而体积更小。
  • 使用 Image Minimizer 对项目中图片进行压缩,体积更小,请求速度更快。(需要注意的是,如果项目中图片都是在线链接,那么就不需要了。本地项目静态图片才需要进行压缩。)
 4.优化代码运行性能
  • 使用 Code Split 对代码进行分割成多个 js 文件,从而使单个文件体积更小,并行加载 js 速度更快。并通过 import 动态导入语法进行按需加载,从而达到需要使用时才加载该资源,不用时不加载资源。
  • 使用 Preload / Prefetch 对代码进行提前加载,等未来需要使用时就能直接使用,从而用户体验更好。
  • 使用 Network Cache 能对输出资源文件进行更好的命名,将来好做缓存,从而用户体验更好。
  • 使用 Core-js 对 js 进行兼容性处理,让我们代码能运行在低版本浏览器。
  • 使用 PWA 能让代码离线也能访问,从而提升用户体验。

#VUE性能优化

一、代码优化

  • 尽量减少 data 中的数据,data 中的数据都会增加 getter 和 setter,会收集对应的 watcher
  • v-if 和 v-for 不能连用, v-for的优先级比v-if高,一起使用会造成性能浪费
  • 如果需要使用 v-for 给每项元素绑定事件时使用事件代理
  • SPA 页面采用 keep-alive 缓存组件
  • 在更多的情况下,使用 v-if 替代 v-show
  • key 保证唯一
  • 使用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动态加载
  • 图片懒加载

二、SEO 优化

  • 预渲染
  • 服务端渲染 SSR

三、打包优化

  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • 使用 cdn 加载第三方模块
  • 多线程打包 happypack
  • splitChunks 抽离公共文件
  • sourceMap 优化

四、用户体验

  • 骨架屏
  • PWA
  • 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启 gzip 压缩等。

vue 中的 spa 应用如何优化首屏加载速度?

优化首屏加载可以从这几个方面开始:

请求优化: CDN 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积,另外 CDN 能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。

缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验

gzip:开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小。

http2:如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。

懒加载:当 url 匹配到相应的路径时,通过 import 动态加载页面组件,这样首屏的代码量会大幅减少,webpack 会把动态加载的页面组件分离成单独的一个 chunk.js 文件

预渲染:由于浏览器在渲染出页面之前,需要先加载和解析相应的 htmlcss 和 js 文件,为此会有一段白屏的时间,可以添加 loading,或者骨架屏幕尽可能的减少白屏对用户的影响体积优化

合理使用第三方库: 对于一些第三方 ui 框架、类库,尽量使用按需加载,减少打包体积

使用可视化工具分析打包后的模块体积webpack-bundle- analyzer 这个插件在每次打包后能够更加直观的分析打包后模块的体积,再对其中比较大的模块进行优化

提高代码使用率: 利用代码分割,将脚本中无需立即调用的代码在代码构建时转变为异步加载的过程

封装: 构建良好的项目架构,按照项目需求就行全局组件,插件,过滤器,指令,utils 等做一些公共封装,可以有效减少我们的代码量,而且更容易维护资源优化

图片懒加载: 使用图片懒加载可以优化同一时间减少 http 请求开销,避免显示图片导致的画面抖动,提高用户体验

使用 svg 图标: 相对于用一张图片来表示图标,svg 拥有更好的图片质量,体积更小,并且不需要开启额外的 http 请求

压缩图片: 可以使用 image-webpack-loader,在用户肉眼分辨不清的情况下一定程度上压缩图片

# 页面加载指标

## API指标

### window.performence.timing

+   fetchStart: 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前。

+   domainLookupStart/domainLookupEnd: DNS 域名查询开始/结束的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,fetchStart 值相等;

+   connectStart: HTTP(TCP)开始/重新 建立连接的时间,如果是持久连接,则与 fetchStart 值相等。

+   requestStart: HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存。

+   responseStart: HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存。

+   responseEnd: HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存。

+   domLoading: 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件。

+   domInteractive: 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件,注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源。

+   domContentLoadedEventStart: DOM 解析完成后,网页内资源加载开始的时间,在 DOMContentLoaded 事件抛出前发生。

+   domContentLoadedEventEnd: DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)。

+   domComplete: DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件。

+   loadEventStart: load 事件发送给文档,也即 load 回调函数开始执行的时间。

+   loadEventEnd: load 事件的回调函数执行完毕的时间。

## 页面指标

### 白屏时间

+ 指浏览器发起请求到开始显示第一个页面元素的时间。现代浏览器不会等待CSS树(所有CSS文件下载和解析完成)和DOM树(整个body标签解析完成)构建完成才开始绘制,而是马上开始显示中间结果。所以经常在低网速的环境中,观察到页面由上至下缓慢显示完,或者先显示文本内容后再重绘成带有格式的页面内容。

+ window.performence.timing.domLoading - window.performence.timing.fetchStart

### 首屏时间

+ 首屏时间(FirstScreen Time),是指用户看到第一屏,即整个网页顶部大小为当前窗口的区域,显示完整的时间。常用的方法有,页面标签标记法、图像相似度比较法和首屏高度内图片加载法。

### 可交互时间

+ 用户可以进行正常的点击、输入等操作,默认可以统计DOMContentLoaded事件发生的时间。

- window.performence.timing.domContentLoadedEventEnd - window.performence.timing.fetchStart

### 整页时间

+ 整页时间(Page Load Time),页面所有资源都加载完成并呈现出来所花的时间,这个就是load事件发生的时间。

- window.performence.timing.loadEventEnd - window.performence.timing.connectStart

## DevTools指标

+ 在使用Google Chrome开发者工具的是,使用Network测试网络性能时候,下面有三个时间。

-   Finish: 1.31s -表示整个页面加载时间为640ms,包括load事件发生后还有一些异步资源也加载完成。

-   DOMContentLoaded: 329ms -发生在页面DOMContentLoaded事件的启动时间点,对应上图蓝色竖线。

-   Load: 1.25s -表示页面load事件的启动时间点,对应上图红色竖线。

结构图

 此章部分内容为网上借鉴内容,如有不满请联系删除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值