前端性能优化(21种优化+7种定位方式),拿去用在工作中

2020-12-2010:43:54WEB前端开发Comments1,460 views字数 9788阅读模式

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

1.重要性

当我们面试的时候,前端性能优化方面算是必考的知识点,但是工作中我们又很少会重点的对项目进行前端优化,它真的不重要吗?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如果我们可以将后端响应时间缩短一半,整体响应时间只能减少5%~10%。而如果关注前端性能,同样是将其响应时间减少一半,则整体响应时间可以减少40%~45%。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

改进前端通常只需要较少的时间和资源,减少后端延迟会带来很大的改动。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

只有10%~20%的最终用户响应时间花在了下载HTML文档上,其余的80%~90%时间花在了下载页面中的所有组件上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.定位

2.1 技术上的选择

在前端日常开发中,技术上的选择是非常重要的。为什么要讲这个呢?因为现象频发。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端工程化严重的当下,轻量化的框架慢慢被遗忘掉了。并不是所有的业务场景都适合使用工程化框架,react/vue 并不轻量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

复杂的框架是为了解决复杂的业务文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如果研发h5、PC展示等场景简单的业务时候,javascript原生 配合一些轻量化插件更适合。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

多页面应用也并不都是缺点。根据业务不同而选择不一样的技术是非常重要的,是每个前端都应该反思的事情。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这方面是导致卡顿的关键问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.2 NetWork

我们的老朋友NetWork想必前端同学都很熟悉。我们先来看一下network面板文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

从面板上我们可以看出一些信息:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 请求资源size
  • 请求资源时长
  • 请求资源数量
  • 接口响应时长
  • 接口发起数量
  • 接口报文size
  • 接口响应状态
  • 瀑布图

瀑布图是什么呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

瀑布图就是上方图片后面的waterfall纵列文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

瀑布图是一个级联图, 展示了浏览器如何加载资源并渲染成网页. 图中的每一行都是一次单独的浏览器请求. 这个图越长, 说明加载网页过程中所发的请求越多. 每一行的宽度, 代表浏览器发出请求并下载该资源的过程中所耗费的时间。它的侧重点在于分析网路链路文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

瀑布图颜色说明:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • DNS Lookup [深绿色] - 在浏览器和服务器进行通信之前, 必须经过DNS查询, 将域名转换成IP地址. 在这个阶段, 你可以处理的东西很少. 但幸运的是, 并非所有的请求都需要经过这一阶段.
  • Initial Connection [橙色] - 在浏览器发送请求之前, 必须建立TCP连接. 这个过程仅仅发生在瀑布图中的开头几行, 否则这就是个性能问题(后边细说).
  • SSL/TLS Negotiation [紫色] - 如果你的页面是通过SSL/TLS这类安全协议加载资源, 这段时间就是浏览器建立安全连接的过程. 目前Google将HTTPS作为其 搜索排名因素 之一, SSL/TLS 协商的使用变得越来越普遍了.
  • Time To First Byte (TTFB) [绿色] - TTFB 是浏览器请求发送到服务器的时间+服务器处理请求时间+响应报文的第一字节到达浏览器的时间. 我们用这个指标来判断你的web服务器是否性能不够, 或者说你是否需要使用CDN.
  • Downloading (蓝色) - 这是浏览器用来下载资源所用的时间. 这段时间越长, 说明资源越大. 理想情况下, 你可以通过控制资源的大小来控制这段时间的长度.

那么除了瀑布图的长度外,我们如何才能判断一个瀑布图的状态是健康的呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 首先, 减少所有资源的加载时间. 亦即减小瀑布图的宽度. 瀑布图越窄, 网站的访问速度越快.
  • 其次, 减少请求数量 也就是降低瀑布图的高度. 瀑布图越矮越好.
  • 最后, 通过优化资源请求顺序来加快渲染时间. 从图上看, 就是将绿色的"开始渲染"线向左移. 这条线向左移动的越远越好.

这样,我们就可以从network的角度去排查“慢”的问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.3 webpack-bundle-analyzer

项目构建后生成的bundle包是压缩后的。webpack-bundle-analyzer是一款包分析工具。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

我们先来看一下它能带来的效果。如下图:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

从上图来看,我们的bundle包被解析的一览无余。其中模块面积占的越大说明在bundle包中size越大。就值得注意了,重点优化一下。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

它能够排查出来的信息有文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 显示包中所有打入的模块
  • 显示模块size 及 gzip后的size

排查包中的模块情形是非常有必要的,通过webpack-bundle-analyzer来排查出一些无用的模块,过大的模块。然后进行优化。以减少我们的bundle包size,减少加载时长。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

安装文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

# NPM 
npm install --save-dev webpack-bundle-analyzer
# Yarn 
yarn add -D webpack-bundle-analyzer
复制代码
复制代码

使用(as a Webpack-Plugin)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
复制代码
复制代码

然后构建包完毕后会自动弹出一个窗口展示上图信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.4 Performance

chrome自带的performance模块。先附上一个官网文档传送门:Performance文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

可以检测很多方面的数据,多数情况的性能排查上用的比较多。如果想要深入了解的同学建议去看一下官方文档。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

接下来我们来说一下在performance面板中如何排差“慢”的问题,它给我们提供了哪些信息呢。先附上一张performance的面板图片。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

从上图中可以分析出一些指标文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • FCP/LCP 时间是否过长?
  • 请求并发情况 是否并发频繁?
  • 请求发起顺序 请求发起顺序是否不对?
  • javascript执行情况 javascript执行是否过慢?

这些指标就是我们需要重点关注的,当然performance的功能并不止于此。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

先记住如何获取到这些指标,后面来一一进行解析优化。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.5 PerformanceNavigationTiming

获取各个阶段的响应时间,我们所要用到的接口是PerformanceNavigationTiming接口。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

PerformanceNavigationTiming 提供了用于存储和检索有关浏览器文档事件的指标的方法和属性。 例如,此接口可用于确定加载或卸载文档需要多少时间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

function showNavigationDetails() {
  const [entry] = performance.getEntriesByType("navigation");
  console.table(entry.toJSON());
}
复制代码

使用这个函数,我们就可以获取各个阶段的响应时间,如图:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

参数说明文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

navigationStart 加载起始时间
redirectStart 重定向开始时间(如果发生了HTTP重定向,每次重定向都和当前文档同域的话,就返回开始重定向的fetchStart的值。其他情况,则返回0)
redirectEnd 重定向结束时间(如果发生了HTTP重定向,每次重定向都和当前文档同域的话,就返回最后一次重定向接受完数据的时间。其他情况则返回0)
fetchStart 浏览器发起资源请求时,如果有缓存,则返回读取缓存的开始时间
domainLookupStart 查询DNS的开始时间。如果请求没有发起DNS请求,如keep-alive,缓存等,则返回fetchStart
domainLookupEnd 查询DNS的结束时间。如果没有发起DNS请求,同上
connectStart 开始建立TCP请求的时间。如果请求是keep-alive,缓存等,则返回domainLookupEnd
(secureConnectionStart) 如果在进行TLS或SSL,则返回握手时间
connectEnd 完成TCP链接的时间。如果是keep-alive,缓存等,同connectStart
requestStart 发起请求的时间
responseStart 服务器开始响应的时间
domLoading 从图中看是开始渲染dom的时间,具体未知
domInteractive 未知
domContentLoadedEventStart 开始触发DomContentLoadedEvent事件的时间
domContentLoadedEventEnd DomContentLoadedEvent事件结束的时间
domComplete 从图中看是dom渲染完成时间,具体未知
loadEventStart 触发load的时间,如没有则返回0
loadEventEnd load事件执行完的时间,如没有则返回0
unloadEventStart unload事件触发的时间
unloadEventEnd unload事件执行完的时间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

关于我们的Web性能,我们会用到的时间参数:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

DNS解析时间: domainLookupEnd - domainLookupStart
TCP建立连接时间: connectEnd - connectStart
白屏时间: responseStart - navigationStart
dom渲染完成时间: domContentLoadedEventEnd - navigationStart
页面onload时间: loadEventEnd - navigationStart文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

根据这些时间参数,我们就可以判断哪一阶段对性能有影响。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.6 抓包

有一些业务状况是没有上述的一些调试工具该怎么办呢?我们可以利用抓包工具进行对页面信息对抓取,上述我们通过chrome工具排查出来的指标,也可以通过抓包工具进行抓取。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这里我推荐一款抓包工具charles文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.7 性能测试工具

2.7.1 Pingdom文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.7.2 Load Impact文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.7.3 WebPage Test文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.7.4 Octa Gate Site Timer文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

2.7.5 Free Speed Test文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.优化

前端的优化种类繁多,主要包含三个方面的优化:网络优化(对加载时所消耗的网络资源优化),代码优化(资源加载完后,脚本解释执行的速度),框架优化(选择性能较好的框架,比如benchmark)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.1 tree shaking

中文(摇树),webpack构建优化中重要一环。摇树用于清除我们项目中的一些无用代码,它依赖于ES中的模块语法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

比如日常使用lodash的时候文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

import _ from 'lodash'
复制代码
复制代码

如果如上引用lodash库,在构建包的时候是会把整个lodash包打入到我们的bundle包中的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

import _isEmpty from 'lodash/isEmpty';
复制代码
复制代码

如果如上引用lodash库,在构建包的时候只会把isEmpty这个方法抽离出来再打入到我们的bundle包中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这样的化就会大大减少我们包的size。所以在日常引用第三方库的时候,需要注意导入的方式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如何开启摇树文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在webpack4.x 中默认对tree-shaking进行了支持。 在webpack2.x 中使用tree-shaking:传送门文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.2 split chunks

中文(分包)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在没配置任何东西的情况下,webpack 4 就智能的帮你做了代码分包。入口文件依赖的文件都被打包进了main.js,那些大于 30kb 的第三方包,如:echarts、xlsx、dropzone等都被单独打包成了一个个独立 bundle。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

其它被我们设置了异步加载的页面或者组件变成了一个个chunk,也就是被打包成独立的bundle。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

它内置的代码分割策略是这样的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 新的 chunk 是否被共享或者是来自 node_modules 的模块
  • 新的 chunk 体积在压缩之前是否大于 30kb
  • 按需加载 chunk 的并发请求数量小于等于 5 个
  • 页面初始加载时的并发请求数量小于等于 3 个

大家可以根据自己的项目环境来更改配置。配置代码如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

splitChunks({
  cacheGroups: {
    vendors: {
      name: `chunk-vendors`,
      test: /[\\/]node_modules[\\/]/,
      priority: -10,
      chunks: 'initial',
    },
    dll: {
      name: `chunk-dll`,
      test: /[\\/]bizcharts|[\\/]\@antv[\\/]data-set/,
      priority: 15,
      chunks: 'all',
      reuseExistingChunk: true
    },
    common: {
      name: `chunk-common`,
      minChunks: 2,
      priority: -20,
      chunks: 'all',
      reuseExistingChunk: true
    },
  }
})
复制代码
复制代码

没有使用webpack4.x版本的项目,依然可以通过按需加载的形式进行分包,使得我们的包分散开,提升加载性能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

按需加载也是以前分包的重要手段之一文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这里推荐一篇非常好的文章:webpack如何使用按需加载文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.3 拆包

与3.2的分包不同。大家可能没发现,上面2.3的bundle包解析中有个有趣的现象,上面项目的技术栈是react,但是bundle包中并没有react、react-dom、react-router等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

因为把这些插件“拆”开了。并没有一起打在bundle中。而是放在了CDN上。下面我举一个例子来解释一下。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

假设:原本bundle包为2M,一次请求拉取。拆分为 bundle(1M) + react桶(CDN)(1M) 两次请求并发拉取。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

从这个角度来看,1+1的模式拉取资源更快。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

换一个角度来说,全量部署项目的情况,每次部署bundle包都将重新拉取。比较浪费资源。react桶的方式可以命中强缓存,这样的化,就算全量部署也只需要重新拉取左侧1M的bundle包即可,节省了服务器资源。优化了加载速度。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

注意:在本地开发过程中,react等资源建议不要引入CDN,开发过程中刷新频繁,会增加CDN服务其压力,走本地就好。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.4 gzip

服务端配置gzip压缩后可大大缩减资源大小。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

Nginx配置方式文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

http {
  gzip on;
  gzip_buffers 32 4K;
  gzip_comp_level 6;
  gzip_min_length 100;
  gzip_types application/javascript text/css text/xml;
  gzip_disable "MSIE [1-6]\.";
  gzip_vary on;
}
复制代码
复制代码

配置完成后在response header中可以查看。 前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.5 图片压缩

开发中比较重要的一个环节,我司自己的图床工具是自带压缩功能的,压缩后直接上传到CDN上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如果公司没有图床工具,我们该如何压缩图片呢?我推荐几种我常用的方式文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 智图压缩 (百度很难搜到官网了,免费、批量、好用)
  • tinypng(免费、批量、速度块)
  • fireworks工具压缩像素点和尺寸 (自己动手,掌握尺度)
  • 找UI压缩后发给你

图片压缩是常用的手法,因为设备像素点的关系,UI给予的图片一般都是 x2,x4的,所以压缩就非常有必要。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.6 图片分割

如果页面中有一张效果图,比如真机渲染图,UI手拿着刀不让你压缩。这时候不妨考虑一下分割图片。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

建议单张土图片的大小不要超过100k,我们在分割完图片后,通过布局再拼接在一起。可以图片加载效率。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这里注意一点,分割后的每张图片一定要给height,否则网速慢的情况下样式会塌陷。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.7 sprite

南方叫精灵图,北方叫雪碧图。这个现象就很有趣。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在网站中有很多小图片的时候,一定要把这些小图片合并为一张大的图片,然后通过background分割到需要展示的图片。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

这样的好处是什么呢?先来普及一个规则文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

浏览器请求资源的时候,同源域名请求资源的时候有最大并发限制,chrome为6个,就比如你的页面上有10个相同CDN域名小图片,那么需要发起10次请求去拉取,分两次并发。第一次并发请求回来后,发起第二次并发。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如果你把10个小图片合并为一张大图片的画,那么只用一次请求即可拉取下来10个小图片的资源。减少服务器压力,减少并发,减少请求次数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

附上一个sprite的例子。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.8 CDN

中文(内容分发网络),服务器是中心化的,CDN是“去中心化的”。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在项目中有很多东西都是放在CDN上的,比如:静态文件,音频,视频,js资源,图片。那么为什么用CDN会让资源加载变快呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

举个简单的例子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

以前买火车票大家都只能去火车站买,后来我们买火车票就可以在楼下的火车票代售点买了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

你细品。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

所以静态资源度建议放在CDN上,可以加快资源加载的速度。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.9 懒加载

懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种非常好的优化网页性能的方式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

当可视区域没有滚到资源需要加载的地方时候,可视区域外的资源就不会加载。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

可以减少服务器负载,常适用于图片很多,页面较长的业务场景中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如何使用懒加载呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.10 iconfont

中文(字体图表),现在比较流行的一种用法。使用字体图表有几种好处文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 矢量
  • 轻量
  • 易修改
  • 不占用图片资源请求。

就像上面说的雪碧图,如果都用字体图标来替换的画,一次请求都免了,可以直接打到bundle包中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

使用前提是UI给点力,设计趋向于字体图标,提前给好资源,建立好字体图标库。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.11 逻辑后移

逻辑后移是一种比较常见的优化手段。用一个打开文章网站的操作来举个例子。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

没有逻辑后移处理的请求顺序是这个样子的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

页面的展示主体是文章展示,如果文章展示的请求靠后了,那么渲染文章出来的时间必然靠后,因为有可能因为请求阻塞等情况,影响请求响应情况,如果超过一次并发的情况的话,会更加的慢。如图的这种情况也是在我们项目中发生过的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

很明显我们应该把主体“请求文章”接口前移,把一些非主体的请求逻辑后移。这样的话可以尽快的把主体渲染出来,就会快很多。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

优化后的顺序是这个样子的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

前端性能优化(21种优化+7种定位方式),拿去用在工作中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在平常的开发中建议时常注意逻辑后移的情况,突出主体逻辑。可以极大的提升用户体验。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.12 算法复杂度

在数据量大的应用场景中,需要着重注意算法复杂度问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在这个方面可以参考Javascript算法之复杂度分析这篇文章。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

如上面Performance解析出的Javascript执行指标上,可以推测出来你的code执行效率如何,如果执行时间过长就要考虑一下是否要优化一下复杂度了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在时间换空间,空间换时间的选择上,要根据业务场景来进行取舍。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.13 组件渲染

拿react举例,组件分割方面不要太深。需要控制组件的渲染,尤其是深层组件的render。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

老生常谈的话题,我们可以一些方式来优化组件渲染文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 声明周期控制 - 比如react的shouldComponentUpdate来控制组件渲染。
  • 官网提供的api- PureComponent
  • 控制注入组件的参数
  • 分配组件唯一key

没有必要的渲染是对性能的极大浪费。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.14 node middleware

中文(node 中间件)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

中间件主要是指封装所有Http请求细节处理的方法。一次Http请求通常包含很多工作,如记录日志、ip过滤、查询字符串、请求体解析、Cookie处理、权限验证、参数验证、异常处理等,但对于Web应用而言,并不希望接触到这么多细节性的处理,因此引入中间件来简化和隔离这些基础设施与业务逻辑之间的细节,让我们能够关注在业务的开发上,以达到提升开发效率的目的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

使用node middleware合并请求。减少请求次数。这种方式也是非常实用的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.15 web worker

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

合理实用web worker可以优化复杂计算任务。这里直接抛阮一峰的入门文章:传送门文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.16 缓存

缓存的原理就是更快读写的存储介质+减少IO+减少CPU计算=性能优化。而性能优化的第一定律就是:优先考虑使用缓存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

缓存的主要手段有:浏览器缓存、CDN、反向代理、本地缓存、分布式缓存、数据库缓存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.17 GPU渲染

每个网页或多或少都涉及到一些CSS动画,通常简单的动画对于性能的影响微乎其微,然而如果涉及到稍显复杂的动画,不当的处理方式会使性能问题变得十分突出。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

像Chrome, FireFox, Safari, IE9+和最新版本的Opera都支持GPU加速,当它们检测到页面中某个DOM元素应用了某些CSS规则时就会开启。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

虽然我们可能不想对元素应用3D变换,可我们一样可以开启3D引擎。例如我们可以用transform: translateZ(0) 来开启GPU加速 。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

只对我们需要实现动画效果的元素应用以上方法,如果仅仅为了开启硬件加速而随便乱用,那是不合理的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.18 Ajax可缓存

Ajax在发送的数据成功后,为了提高页面的响应速度和用户体验,会把请求的URL和返回的响应结果保存在缓存内,当下一次调用Ajax发送相同的请求(URL和参数完全相同)时,它就会直接从缓存中拿数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

在进行Ajax请求的时候,可以选择尽量使用get方法,这样可以使用客户端的缓存,提高请求速度。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.19 Resource Hints

Resource Hints(资源预加载)是非常好的一种性能优化方法,可以大大降低页面加载时间,给用户更加流畅的用户体验。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

现代浏览器使用大量预测优化技术来预测用户行为和意图,这些技术有预连接、资源与获取、资源预渲染等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

Resource Hints 的思路有如下两个:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

  • 当前将要获取资源的列表
  • 通过当前页面或应用的状态、用户历史行为或 session 预测用户行为及必需的资源

实现Resource Hints的方法有很多种,可分为基于 link 标签的 DNS-prefetch、subresource、preload、 prefetch、preconnect、prerender,和本地存储 localStorage。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.20 SSR

渲染过程在服务器端完成,最终的渲染结果 HTML 页面通过 HTTP 协议发送给客户端,又被认为是‘同构'或‘通用',如果你的项目有大量的detail页面,相互特别频繁,建议选择服务端渲染。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

服务端渲染(SSR)除了SEO还有很多时候用作首屏优化,加快首屏速度,提高用户体验。但是对服务器有要求,网络传输数据量大,占用部分服务器运算资源。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

Vue的Nuxt.js和React的next.js都是服务端渲染的方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

3.21 UNPKG

UNPKG是一个提供npm包进行CDN加速的站点,因此,可以将一些比较固定了依赖写入html模版中,从而提高网页的性能。首先,需要将这些依赖声明为external,以便webpack打包时不从node_modules中加载这些资源,配置如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

externals: { 'react': 'React' }
复制代码

其次,你需要将所依赖的资源写在html模版中,这一步需要用到html-webpack-plugin。下面是一段示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

<% if (htmlWebpackPlugin.options.node_env === 'development') { %>
  <script src="https://unpkg.com/react@16.7.0/umd/react.development.js"></script>
<% } else { %>
  <script src="https://unpkg.com/react@16.7.0/umd/react.production.min.js"></script>
<% } %>
复制代码

这段代码需要注入node_env,以便在开发的时候能够获得更友好的错误提示。也可以选择一些比较自动的库,来帮助我们完成这个过程,比如webpack-cdn-plugin,或者dynamic-cdn-webpack-plugin文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

4.总结

还有一些比较常用的优化方法我没有列举出来,例如将样式表放在顶部,将脚本放在底部,减少重绘,按需加载,模块化等。方法很多,对症下药才是关键。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

作者:黑色的枫
链接:https://juejin.cn/post/6904517485349830670
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/20759.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/gcs/20759.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定