本文主要讲述,关于 Chrome Content Download 时间过长问题调查经过,及相关优化方案

chunk-136cc8c0.js 是上图地图 geojson,587 kB 用了 1.01s,作为系统首页,会导致中间地图(视觉中心)出现长时间的空白,对于用户体验来说,极其不友好。

怀疑一:是不是网络环境不好导致?

在开发环境下运行(本地)也会出现类似情况,且更重要的是 chunk-7182b1fa.js 933kB 才用了 35ms。因此可以排除网络坏境导致。

怀疑二:缓存导致?

某些 chunk 请求用时短,某些请求用时长;是不是缓存起的作用。

  1. 缓存(304)的确可以加快资源的请求
  2. 但对于 chunk-136cc8c0.js 和其他请求依然不是一个量级的

怀疑三:浏览器并行加载个数有限,导致排队时间过长?

Chrome 浏览器默认并行加载个数为 6 个,过多的请求的确会引起资源请求排队。

通过 Chrome => Network => Timing 查看:

  • Queueing(排队): 浏览器会在以下情况下对请求进行队列处理:

    • 有更高优先级的请求。(浏览器 Network 中可以通过 Priority 查看)
    • 已经建立了 6 个 TCP 连接(HTTP/1.0和HTTP/1.1协议下的限制)
    • The browser is briefly allocating space in the disk cache
  • Stalled(阻塞): 请求可能会因为 Queueing 中描述的任何原因而停止

  • Request sent(发送请求): 发送HTTP请求的时间(从第一个bit到最后一个bit)

  • Waiting (TTFB)(等待响应): 浏览器正在等待响应的第一个字节。TTFB表示时间到第一个字节。这个时间包括1个延迟往返和服务器准备响应所花费的时间

  • Content Download(下载): 下载HTTP响应的时间(包含头部和响应体)

整体 Queueing(排队)并没有消耗多少时间(1.28ms),而是 Content Download 消耗了大量时间(1.01s)。所以断定并不是排队时间过长导致该问题。

更详细的,可以查看 Chrome 开发文档:这里

怀疑四:Cpu 被耗尽,浏览器”停顿“?

查了相关的帖子,这篇 最后的回答「Frontend app is doing too much work」给了另一个方向。

是不是初始阶段进行大量的 JS 工作,导致 cpu 被耗尽了,使得浏览器处于了”停顿“状态。

通过 Chrome => Performance => Start recording:

chunk-136cc8c0.js 加载前后 cpu 使用率为 100%,导致资源请求和后续等待执行的时间都很长。初步断定,和 cpu 占用率用很大关系。


问题有了方向,后续就是针对问题出各种优化方案


优化方式

通用:开启缓存

Nginx 开启静态资源(css、js)缓存配置:

在 server 中的 location / 的配置中增加如下配置

location / {if ($request_filename ~* ^.*?\.(js|css)$){# 缓存时效性可以根据项目诉求,自行设定expires 30d;}root xxx/dist;index index.html;....
}

通用:开启 Gzip

对静态资源进行 gzip,能起到巨大的效果(实测:40M的内容,gzip完不足10M)。

第1步:按照依赖

$ npm install compression-webpack-plugin --save-dev

第2步:vue.config.js 开启 gzip 压缩

const CompressionPlugin = require("compression-webpack-plugin");module.exports = {plugins: [new CompressionPlugin()],
};

详细配置可查看 compression-webpack-plugin

第3步:在 Nginx 配置文件中的 http 或者 server 中增加配置

server {gzip  on;gzip_vary on;gzip_types application/javascript text/css;location / {...}
}

由于是 geojson,压缩空间有限但也减少了一半,对于 http 请求速度会有很大的提高(对于纯 css、js代码,效果会更加明显)。

可选:动态延迟加载

页面中存在好多 Dialog 等下钻需要的组件,可以通过 webpack import() 动态加载,避免进入页面全部发起请求。

import() 可以动态的加载模块。调用 import 的之处,被视为分割点,被请求的模块和它引用的所有子模块,会分割到一个单独的 chunk 中。

原形式:

import detailEventDialog from './components/detail-event.vue'
import detailVulnDialog from './components/detail-vuln.vue'
import detailCompDialog from './components/detail-comp.vue'
import detailWeakDialog from './components/detail-weak.vue'
import detailWeakTabDialog from './components/detail-weak-tab.vue'
import detailAssetDialog from './components/detail-asset.vue'
import detailUserDialog from './components/detail-user.vue'export default {components: {detailEventDialog, detailVulnDialog,detailCompDialog,detailWeakDialog,detailWeakTabDialog,detailAssetDialog,detailUserDialog}
}

修改后:

export default {components: {detailEventDialog: () => import('./components/detail-event.vue'),detailVulnDialog: () => import('./components/detail-vuln.vue'),detailCompDialog: () => import('./components/detail-comp.vue'),detailWeakDialog: () => import('./components/detail-weak.vue'),detailWeakTabDialog: () => import('./components/detail-weak-tab.vue'),detailAssetDialog: () => import('./components/detail-asset.vue'),detailUserDialog: () => import('./components/detail-user.vue')}
}

import() 必须至少包含一些关于模块的路径信息。打包可以限定于一个特定的目录或文件集,以便于在使用动态表达式时 - 包括可能在 import() 调用中请求的每个模块。例如, import(./locale/${language}.json) 会把 .locale 目录中的每个 .json 文件打包到新的 chunk 中。在运行时,计算完变量 language 后,就可以使用像 english.jsongerman.json 的任何文件。 – webpack import

可选:DOM逐针渲染

vue mixins

export default function (maxCount = 0) {return {data () {return {// 展示权重,默认为0displayPriority: 0,running: true}},mounted () {this._startLoop()},methods: {_startLoop () {// 最大渲染数为0时,停止助阵逐帧渲染if (maxCount === 0) returnthis.running = trueconst step = () => {this.displayPriority++if (this.running && this.displayPriority <= maxCount) {requestAnimationFrame(step)}}requestAnimationFrame(step)},_stopLoop () {this.running = false},delayRender (priority) {return this.displayPriority >= priority}},activated () {// 激活状态开始渲染!this.running && this._startLoop()},deactivated () {// 停止渲染监听this._stopLoop()},beforeDestroy () {// 停止渲染监听this._stopLoop()}}
}

使用

<template><div><el-row>...</el-row><el-row v-if="delayRender(3)">...</el-row><el-row v-if="delayRender(6)">...</el-row><el-row v-if="delayRender(9)">...</el-row></div>
</template>
<script>export default {mixins: [delayRenderService(9)]}
</script>

针对业务代码瘦身

针对特定业务需求,对静态资源进行了瘦身(删除了一些无用的第三方、自研组件、及静态资源的引用);然后将 chunk-136cc8c0.js(geojson) 加载时机提前,获取到资源后,先行渲染底图。

最小化主线程工作

浏览器的渲染器进程将代码转换为用户可以与之交互的网页。默认情况下,渲染器进程的主线程通常处理大部分代码:它解析 HTML 并构建 DOM,解析 CSS 并应用指定的样式,以及解析、评估和执行 JavaScript。主线程还处理用户事件。因此,每当主线程忙于做其他事情时,网页可能无法响应用户交互,从而导致糟糕的体验。

方式
Script evaluation 优化第三方 JavaScript
去抖动输入处理程序
使用网络工作者
Style and layout 减少样式计算的范围和复杂性
避免大型、复杂的布局和布局颠簸
Rendering 坚持只使用合成器的属性并管理层数
简化油漆复杂性并减少油漆区域
Parsing HTML and CSS 提取关键 CSS
缩小 CSS
推迟非关键 CSS
Script parsing and compilation 通过代码拆分减少 JavaScript 负载
删除未使用的代码
Garbage collection 使用以下命令监控网页的总内存使用情况 measureMemory()

最终效果

性能调优--gzip、缓存、content-download、逐针渲染、Queueing、动态延迟加载、最小化主线程工作相关推荐

  1. Redis基础用法、高级特性与性能调优以及缓存穿透等分析

    目录 一.Redis介绍 二.Redis数据结构及常用的命令 三.Redis持久化策略选择 四.内存管理与数据淘汰机制 五.Redis过期策略及实现原理 1  说明 2  设置过期时间 3  三种过期 ...

  2. SPDK RBD bdev性能调优

    前言    在前文[1]中,我们简述了SPDK中RBD bdev模块以及所依赖的librbd接口的调用方法.本文就SPDK RBD bdev结合Ceph RBD的使用进行更为深入的探讨,并结合实际的应 ...

  3. Ceph分布式存储(架构 配置与使用 原理 性能调优)

    Ceph分布式存储 Ceph分布式存储 1. Ceph概述 1.1 背景 1.2 介绍 1.3 特点 1.4 分布式存储系统横纵对比 2. Ceph架构设计 2.1 Ceph整体设计 2.2 逻辑架构 ...

  4. iOS应用性能调优的25个建议和技巧【转】

    转载自:http://blog.jobbole.com/37984/ 首页 最新文章 资讯 程序员 设计 IT技术 创业 在国外 营销 趣文 特别分享 更多 > - Navigation - 首 ...

  5. 程序员精进之路:性能调优利器--火焰图

    作者:厉辉,腾讯 CSIG 后台开发工程师 本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一 ...

  6. 参数调优为什么要采样_程序员精进之路:性能调优利器--火焰图

    本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一下,曾经作为编程新手的我们是如何调优程序的? ...

  7. iOS应用性能调优建议

    本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/,你还可以 ...

  8. iOS应用性能调优的25个建议和技巧

    写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/ ...

  9. 编程新手该如何调优程序?程序员必备性能调优利器——火焰图

    本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一下,曾经作为编程新手的我们是如何调优程序的? ...

最新文章

  1. tc溜溜865手机投屏卡_游戏物理外挂再升级!腾讯黑鲨游戏手机3S开箱体验
  2. 简单的了解一下AQS吧
  3. trinitycore MySQL模块_Windows下编译TrinityCore服务端
  4. C#LeetCode刷题-脑筋急转弯
  5. oracle全角括号忽略,Oracle中SQL查询语句日文不区分全角/半角
  6. editplus java acp_EditPlus配置Java编译器
  7. 时域分析——有量纲特征值含义一网打尽
  8. 基于图像识别的火灾探测技术
  9. LeetCode_回文数(三种解法-Java)
  10. Parcel 中文文档 | Parcel 中文网
  11. HackTheBox - Unified
  12. (一)Redis——五大数据类型及基础知识
  13. 大一学生《Web编程基础》期末网页制作 HTML+CSS+JavaScript 企业网页设计实例
  14. hangye5:2345导航将出嫁史玉柱 网址站出路大盘点
  15. 云端服务器维护,云端服务器维护
  16. Json完整版介绍和工具类解析应用
  17. 单相逆变器及基于STM32 SPWM生成代码
  18. js中如何判断是否是数组?
  19. java 工厂模式实现_Java三种实现工厂模式的方法
  20. 网络字节顺序 大头小头问题

热门文章

  1. 老师教我们用计算机画画就是彩虹,一年级上课文
  2. JAVA学习笔记五---函数
  3. mysql 5.7版本异常Expression #1 of ORDER BY clause is not in GROUP BY clause and contains 处理
  4. [MOOC]物联网技术笔记-2.物联网的概念和特征
  5. 备份谷歌或其他浏览器插件
  6. 十大算法--支持向量机
  7. 2019蓝桥杯国赛总结
  8. 微信小程序|使用小程序制作一个足球拼图小游戏
  9. OaisimWithS1搭建笔记(2019.5)
  10. 飞桨day-04 NLP实践作业