前端性能优化总结

gzip压缩

gzip压缩效率很高,可以达到70%的压缩率

//npm i -D compression-webpack-plugin  安装插件依赖
configureWebpack: config => {
  const CompressionPlugin = require('compression-webpack-plugin')
  config.plugins.push(new CompressionPlugin())
}



去掉console.log

生产环境中,不需要打印日志。通过对webpack进行配置,打包时自动去掉console.log

//npm i -D terser-webpack-plugin
configureWebpack:config =>{
    const  TerserPlugin = require('terser-webpack-pulugin')
    config.optimzation.minimizer.push(
        new TerserPlugin({
            extractComments:false,
            terserOptions:{compress:{drop_console:true}} //插件配置项 移除console
        })
    )
}



去除SourceMap

代码压缩后进行调bug定位将非常困难,于是引入sourcemap记录压缩前后的位置信息记录,当产生错误时直接定位到未压缩前的位置,将大大的方便我们调试。

sourcemap附带了很多信息,如果build需要生成sourcemap,将会大大降低build的速度,还会增加包的体积。

//vue 中
module.exports = {
  productionSourceMap: false,
}

//react中
//打开webpack.config.prod.js
const shouldUseSourceMap = false



CDN

内容分发网络,它能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。所以可以通过将资源部署在CDN上来提高响应速度,提高用户体验
预渲染

简单来说,就是将浏览器解析JavaScript动态渲染的工作,在打包阶段完成了(只构建了静态数据)。换个说法,在构建过程中,webpack通过使用prerender-spa-plugin插件生成静态结构的html

// 1、安装prerender-spa-plugin
npm install prerender-spa-plugin --save-dev
 
// 2、安装vue-meta-info
npm install vue-meta-info --save-dev
 
 
// 3、相关配置
<!-- webpack.prod.conf.js -->
// 预渲染配置:在webpack.prod.conf文件中加入
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
 
// 在 plugins 中加入
new PrerenderSPAPlugin({
      // 生成文件的路径,也可以与webpakc打包的一致。
      // 下面这句话非常重要!!!
      // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
      staticDir: path.join(__dirname, '../dist'),
 
      // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
      routes: ['/', '/first', '/second', '/third', '/fourth', '/userCenter/userFirst','/userCenter/userSecond','/userCenter/userThird'],
 
      // 这个很重要,如果没有配置这段,也不会进行预编译
      renderer: new Renderer({
        inject: {
          foo: 'bar'
        },
        // headless: false,
        renderAfterDocumentEvent: 'render-event', // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
        args: ['--no-sandbox', '--disable-setuid-sandbox']
      })
    })
 
// 4、在main.js中
import MetaInfo from 'vue-meta-info'
 
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>',
  // 添加mounted,不然不会执行预编译
  mounted () {
    document.dispatchEvent(new Event('render-event'))
  }
})



注意:路由模式必须为 history ,如果不设置 history 模式,也能运行和生成文件,每个 index.html 文件的内容都会是一样的
Service Worker

ServiceWorker 是运行在浏览器后台进程里的一段 JS,它可以做许多事情,比如拦截客户端的请求、向客户端发送消息、向服务器发起请求等等,其中最重要的作用之一就是离线资源缓存。

ServiceWorker 拥有对缓存流程丰富灵活的控制能力,当页面请求到 ServiceWorker 时,ServiceWorker 同时请求缓存和网络,把缓存的内容直接给用户,而后覆盖缓存

注意:需要HTTPS才能使用ServiceWorker
HTTP缓存

HTTP缓存一般分为两类:强缓存(本地缓存)、协商缓存(304缓存)

普通刷新会启用协商缓存

在地址栏输入网址、通过链接引入资源等情况下,浏览器才启用强缓存

强缓存(200)。本地缓存是最快速的一种缓存方式,只要资源还在缓存有效期内,浏览器就会直接在本地读取,不会请求服务端。在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。

协商缓存(304)。协商缓存,顾名思义是经过浏览器与服务器之间协商过之后,在决定是否读取本地缓存,如果服务器通知浏览器可以读取本地缓存,会返回304状态码,并且协商过程很简单,只会发送头信息,不会发送响应体。

协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag

首先在精确度上,Etag要优于Last-Modified

第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值

第三在优先级上,服务器校验优先考虑Etag

缓存优先级:Service Worker -> Memory Cache(内存缓存) -> Disk Cache(硬盘缓存) -> Push Cache(推送缓存)

Push Cache 只在会话(session)中存在,会话结束就被释放,而且缓存时间很短
HTTP2

HTTP2 四个新特性:

    多路复用,无需多个TCP连接,因为其允许在单一的HTTP2连接上发起多重请求,因此可以不用依赖建立多个TCP连接。
    二进制分帧,将所有要传输的消息采用二进制编码,并且会将信息分割为更小的消息块。
    头部压缩,用HPACK技术压缩头部,减小报文大小
    服务端推送,服务端可以在客户端发起请求前发送数据,换句话说,服务端可以对客户端的一个请求发送多个相应,并且资源可以正常缓存。

server {
    listen 443 ssl http2;
}


资源预加载

提前加载资源,当用户需要时,可以直接从本地缓存中渲染。
preload

页面加载的过程中,在浏览器开始主体渲染之前加载

//对sty1e.cs5和 index.js进行pre1oad预加载
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="index.js" as="script">



prefetch

页面加载完成后,利用空闲时间提前加载

//对资源进行 prefetch预加载
<link rel="prefetch" href="next.css">
<link rel="prefetch" href="next.js">


dns-prefetch

//对特定域名进行预解析
//将静态资源只放在一个域名下面,可以有效减少dns的请求
<link rel=”dns-prefetch” href=”//fonts.googleapis.com”>


异步无阻塞加载JS

异步加载 js 文件,并且不会阻塞页面的渲染。

普通的script标签在开始解析和解析的过程中,会停止解析dom
defer

<script src="d.js" defer></script> <script src="e.js" defer></script>


在其他同步脚本执行后,DOMContentLoaded 事件前 依次执行 d.js, e.js。
async

<script src="b.js" async></script>
<script src="c.js" async></script>
当脚本下载完后立即执行。(两者执行顺序不确定,执行阶段不确定,可能在 DOMContentLoaded 事件前或者后 )

defer和async都不会停止解析dom
webp

webp 是一种新的图片格式,它的体积只有只有 jpeg的2/3,将图片资源大量换成 webp 格式可以加快请求的速度

但是webp存在浏览器兼容问题,使用前需要判断浏览器是否支持
loading加载

通过添加加载中状态,可以让用户在视觉上不会觉得慢

可以通过骨架屏加载,在感官上内容出现的流畅不突兀