不到一秒才叫优化

简介: 之前做完的一个项目,业务逻辑写完之后,首屏渲染能到3~4秒,这对于用户体验是不能接受的,所以忙里偷闲把项目优化完之后http发送到响应时间:705ms,DOM构建完毕:452ms,页面加载完毕:678ms,清爽的感觉很上头~看来优化还是很有必要的!所以本篇记录一下优化过程。

网络异常,图片无法展示
|

之前做完的一个项目,业务逻辑写完之后,首屏渲染能到3~4秒,这对于用户体验是不能接受的,所以忙里偷闲把项目优化完之后:

网络异常,图片无法展示
|

http发送到响应时间:705ms,DOM构建完毕:452ms,页面加载完毕:678ms,清爽的感觉很上头~看来优化还是很有必要的!所以本篇记录一下优化过程。


正文


  1. UglifyJsPlugin
    UglifyJsPlugin 是一个webpack的解析、混淆、压缩JS的工具,低版本的 UglifyJsPlugin 是不支持ES6的,所以在使用的时候要注意要么升级版本,要么添加文件 .bablelrc,在里面添加
{
  "pressets": ["es2015"]
}
  1. cdn
    cdn 的话,尽可能把所有资源都使用cdn,比如 vuevuexvue-routeraxiosechart,举个例子:
// cdn链接
const cdn = {
  externals: {
    echarts: "echarts",
    "ant-design-vue": "AntDesignVue",
    vue: "Vue",
    "vue-router": "VueRouter",
    vuex: "Vuex",
    axios: "axios"
  },
  // cdn的css链接
  css: [],
  // cdn的js链接
  js: [
    "https://cdn.jsdelivr.net/npm/echarts@4/dist/echarts.min.js",
    "https://cdn.bootcss.com/vue/2.6.10/vue.min.js",
    "https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js",
    "https://cdn.bootcss.com/vue-router/3.0.7/vue-router.min.js",
    "https://cdn.bootcss.com/axios/0.18.0/axios.min.js"
  ]
};
  1. 然后在两个地方使用,一个是webpack的 chainWebpack 配置,一个是 configureWebpack 的配置:
// 是否为生产环境
const isProduction = process.env.NODE_ENV !== "development";
// 本地环境是否需要使用cdn
const devNeedCdn = true;
module.exports = {
  // webpack 配置
  chainWebpack: config => {
    // ...
    config.plugin("html").tap(args => {
      // 生产环境或者本地需要cdn时,才注入cdn
      if (isProduction || devNeedCdn) args[0].cdn = cdn;
      return args;
    });
  },
  configureWebpack: config => {
    // 用cdn方式引入,则构建时要忽略相关资源
    if (isProduction || devNeedCdn) config.externals = cdn.externals;
  }
}
  1. 这样 cdn 就配置好了,如果想在开发环境也使用它的话,需要在入口文件 index.html 中把CSS和JS的资源加载改成:
<!-- 使用CDN的CSS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn &&
   htmlWebpackPlugin.options.cdn.css) { %>
<link
   href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
   rel="stylesheet"
/>
<% } %>
<!-- 使用CDN的JS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn &&
  htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> 
<% } %>
  1. 相当于动态加载了webpack配置里的cdn文件。
  2. CompressionWebpackPlugin
    CompressionWebpackPlugin 是webpack的 Gzip 压缩插件,官方介绍是:提供带 Content-Encoding 编码的压缩版的资源,下面是它的配置项:
配置项 类型 默认值 描述
test {RegExp} . 处理所有匹配此 {RegExp} 的资源
asset {String} [path].gz[query] 目标资源名称。[file] 会被替换成原资源。[path] 会被替换成原资源路径, [query] 替换成原查询字符串
filename {Function} false 一个 (asset) => asset 函数,接收原资源名(通过 asset 选项)返回新资源名
algorithm {String|Function} gzip 可以是 (buffer, cb) => cb(buffer) 或者是使用 zlib 里面的算法的 {String}
threshold {Number} 0 只处理比这个值大的资源。按字节计算
minRatio {Number} 0.8 只有压缩率比这个值小的资源才会被处理
deleteOriginalAssets {Boolean} false 是否删除原资源
  1. 这边我用了网上大家常用的配置:
configureWebpack: config => {
  const productionGzipExtensions = ["html", "js", "css"];
  config.plugins.push(
    new CompressionWebpackPlugin({
      filename: "[path].gz[query]",
      algorithm: "gzip",
      test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
      threshold: 10240, // 只有大小大于该值的资源会被处理 10240
      minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
      deleteOriginalAssets: false // 删除原文件
    })
  );
}
  1. 注意,如果使用 Gzip 的话,打包后会出现一个 x.gz 文件,比如 index.html,打包后会多一个 index.html.gz 文件,如果服务器端(nginx等)不开启 gzip 功能,加载的其实还是 index.html,开启之后就会加载 index.html.gz 来替代加载 index.html了。
    在 nginx 中可以这么配置(nginx.conf):
#gzip  on;
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式,后面的图片压缩不需要的可以自行删除
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置压缩所需要的缓冲区大小     
gzip_buffers 4 16k;
  1. 重启之后查看请求接口的响应头的 Content-Encodinggzip 的话说明开启成功。
  2. moment
    由于用到了 moment,所以也得把它压缩一下,它可是贼大的,因为它的npm包里加载了很多的语言版本,所以一般情况下,只需要中文版就可以了,所以在webpack的配置里,把moment的语言包给忽略掉,然后在 main.js 中加载一个语言包 import "moment/locale/zh-cn",这样体积就会小很多。
  3. splitChunks
    splitChunks 可以对大包进行拆分,对小包进行合并,防止模块重复打包,从而减少请求资源的大小和此时,这个要根据实际情况去调整。
  4. 代码逻辑加了以上的操作之后,可以使用插件webpack-bundle-analyzer来看下优化的效果,如果还有大块的,就把业务继续优化,主要从引用、封装入手,能抽出来的尽量抽出来,把工具和业务分开。以vue为例的话,可以注意以下几点:
  1. v-if 和 v-show
    v-if 适合条件改变很少的情况,v-show 适合频繁切换条件的情况
  2. computed 和 watch
    computed 适合在计算和依赖场景使用,watch 适合数据变化的异步操作
  3. v-for 必须添加 key
    vue的 diff 算法会关联到 key,所以当状态更新时,key的作用很大,为了优化效率,建议添加key(现在开发工具已经做了提醒)
  4. v-for 里不使用 v-if
    v-for 的优先级要比 v-if 高,如果vue的循环节点每次都重新遍历整个数组,就需要花很多时间
  5. event
    在页面上使用了事件之后,离开的时候最好把事件给销毁(全局除外),可以防止内存泄漏(比如图表的加载和重绘)
  6. 图片懒加载
    图片资源懒加载可以使用 vue-lazyload 插件,保证只加可视区域内的图片
  7. 路由懒加载
    如果不用路由懒加载的话,页面访问就会把所有路由都加载完毕之后再加载,如果资源过多,白屏的出现几率就会大大增加,所以路由要改成只在访问的时候加载:component: () => import("./views/Login.vue")
  8. 三方插件按需引入
    很多三方插件包很大,所以它们大部分也都给了按需加载的使用说明
  9. 防抖和节流
    对于触发事件的时间和时机判定,防止用户频繁点击和误操作,它们两个也算优化的一部分
目录
相关文章
|
10月前
|
Linux C语言 C++
现代c++中实现精确延时方法总结
现代c++中实现精确延时方法总结
|
11月前
AS执行时间计算
long start=System.currentTimeMillis();
34 0
|
SQL 关系型数据库 MySQL
mysql查询优化实战:查询用时一分半降到三毫秒
项目中的课程预约记录查询功能,线下门店反馈说进入到页面需要等2分钟
mysql查询优化实战:查询用时一分半降到三毫秒
|
canal 架构师 数据库
处理亿级数据的“定时任务”,如何缩短执行时间?
一次性集中处理大量数据的定时任务,优化思路是:同一份数据,减少重复计算次数;分摊CPU计算时间,尽量分散处理(甚至可以实时),而不是集中处理;减少单次计算数据量。
1613 0
处理亿级数据的“定时任务”,如何缩短执行时间?
|
C++ Windows
c++计算代码执行时间的方法,毫秒级
方法一、 #include#includeusing namespace std;class CTimer{public:CTimer(){_start=clock();}~CTimer(){_end=clock();cout
1099 0
这样统计代码执行耗时,才足够优雅!
代码耗时统计在日常开发中算是一个十分常见的需求,特别是在需要找出代码性能瓶颈时。 可能也是受限于 Java 的语言特性,总觉得代码写起来不够优雅,大量的耗时统计代码,干扰了业务逻辑。特别是开发功能的时候,有个感受就是刚刚开发完代码很清爽优雅,结果加了一大堆辅助代码后,整个代码就变得臃肿了,自己看着都挺难受。因此总想着能不能把这块写的更优雅一点,今天本文就尝试探讨下“代码耗时统计”这一块。
|
移动开发 小程序 Java
这4种统计代码执行耗时,才足够优雅!
今天,跟大家分享一下,如何在代码中,统计接口耗时,最优雅,性能最高,接下来我将介绍4种统计方式,如果你有更好的方式,欢迎文末留言区,交流
724 0
这4种统计代码执行耗时,才足够优雅!
|
数据库
一次性集中处理大量数据的定时任务,如何缩短执行时间?
处理亿级数据的“定时任务”,如何缩短执行时间?
|
SQL 存储 算法
翻动100万级的数据 —— 只需几十毫秒
感谢大家的支持!!! 昨天发了一个邀请,邀请大家帮忙测试,效果还可以,下面小结一下: 通过内部的计数器得知:访问次数是1071(其中有好多是自己点的:)),人数不是太理想,本来是想看看上万人同时访问的情况:) 系统资源的占用情况内存 —— 很理想。
1708 0