前言

  前几天开会的时候,被老板质问为何打开网址等了8、9秒?当时我既然语塞,因为安卓和IOS打开也很慢,但不会像PC网页这么慢到接近10秒才打开。而且更要命的是服务器在新加坡,老板就是在新加坡打开这么慢,我在国内打开往往花了一分钟以上,最慢的时候达到3分40秒,这速度是要命的!因为3秒定律,过了3秒用户是没有耐心直接关闭,如果是国外的网址愿意多等一会,但也不可能愿意等这么久!

  于是乎这周除了修复几个bug和新增了一些功能之外,我首要的任务就是优化网站加载!

  当然以下优化都是建立在网速正常的情况下。

 

优化vue项目

  第一步:增加页面加载动画

    国际网站给多个国家使用,因为再怎么优化,首次进入都一定有几秒的等待时间,这个时候加一个炫酷的动画往往能使用户分心,不会过于焦躁,而网站在第一次加载之后,后面更新了也不需要再等待那么久,利用缓存基本能秒更新。

    

 

     有兴趣的伙伴可以到我的github下载: https://github.com/13632756286/Loading-

 

  第二步:vue-router 路由懒加载

    见名知意,路由懒加载既是组件的延迟加载,通常vue的页面在运行后进入都会有一个默认的页面,而其他页面只有在点击后才需要加载出来。使用懒加载可以将页面中的资源划分为多份,从而减少第一次加载的时候耗时。

 

     相关代码:

       1. router/index.js

const Home = resolve => require(['@/views/Home/HomePage'], resolve);
const Login = resolve => require(['@/views/Login/LoginPage'], resolve);
const Error = resolve => require(['@/components/Error/Error'], resolve);
const PrintPage = resolve => require(['@/views/Print/printPage'], resolve);
const PayNow = resolve => require(['@/views/Print/PayNow'], resolve);
const HomePage = resolve => require(['@/components/Home/homePage'], resolve);

const router =  new Router({
  routes: [
    {
      path: '/home',
      name: 'home',
      component:Home,
      children:[
        { path: "",name: 'homePage',component: HomePage, props:true },
        { path: "printPage",name: 'printPage',component: PrintPage, props:true },
        { path: "payNow",name: 'payNow',component: PayNow, props:true }
      ],
    },
    {
      path: '/login',
      name: 'login',
      component:Login,
    },
    {
      path: '/register',
      component:Login,
    },
    {
      path:'/*',
      component:Error
    }
  ]
});

  

      2. 父组件引入子组件时:

  components: {
    // 组件的按需懒加载
    navMenu: resolve => require(["@/components/Util/Menu/navMenu.vue"], resolve),
    TransactionsBox: resolve => require(["@/components/Home/transactions.vue"], resolve),
    topUp: resolve => require(["@/components/Home/topUp.vue"], resolve),
    DebitCard: resolve => require(["@/components/Home/debitCard.vue"], resolve),
    SettingsBox: resolve => require(["@/components/Home/settings.vue"], resolve),
    ProfileSelect: resolve => require(["@/components/Util/Select/profileSelect.vue"], resolve),
    headerBox: resolve => require(["@/components/Util/Head/header.vue"], resolve),
    AddCardDialog: resolve => require(['@/components/Util/CardBox/addCardDialog.vue'],resolve)
  }

 

      3. 关闭vuecli 3默认开启的prefetch(预先加载模块)

        首屏加载的时候,默认会把分割的十几个路由文件全部下载,提前获取用户未来可能访问的内容,在这里建议关闭,可以在vue.config.js中设置:

module.exports = {
    chainWebpack: config => {
        // 移除 prefetch插件
        config.plugins.delete('prefetch')
    }
}

        或者修改其选项:

module.exports = {
    config.plugin('prefetch').tap(options => {
        options[0].fileBlacklist = options[0].fileBlacklist || [];
        options[0].fileBlacelist.push(/myasyncRoute(.)+?\.js$/);
        return options;
    })
}

      当prefetch插件被禁用时,你可以通过webpack的内联注释手动选定要提前获取的代码:

import(/* webpackPrefetch: true */ './someAsyncComponent.vue');

      设置完毕之后,首屏就只会加载当前页面的路由组件了。

 

 

  第三步:使用CDN减小代码体积加快请求速度

    CDN的好处:

      1.CDN采取的是就近原则下载,速度较快;

      2.减少打包体积,这也意味着请求该网址的下载速度会更快;

 

    相关代码

      1. public/index.html

  <script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
  <link href="https://cdn.bootcss.com/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet">
  <script src="https://cdn.bootcss.com/element-ui/2.13.0/index.js"></script>
  <script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>
  <script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
  <script src="https://cdn.bootcss.com/vue-i18n/8.17.0/vue-i18n.min.js"></script>
  <script src="https://cdn.bootcss.com/vuex/3.1.3/vuex.min.js"></script>

 

      2. 删除main.js当中的相关代码,例:import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI); 等等,如果这些代码没有删除,那么打包的时候还是会自动在node_modules中引入下载,打包的体积还是会很大!

 

      3. vue.config.js中设置禁止引入上述的包进行打包(如果没有vue.config.js就自己在根目录创建)

configureWebpack: config => {
      return {
        externals: { //externals 里的库不会被webpack打包
          'echarts': 'echarts',
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'ElementUI': 'ELEMENT',
          'axios': 'axios',
          'vue-resource': 'VueResource',
          'vuex': 'Vuex',
          'vue-i18n': 'VueI18n',
          "qs": "qs",
          "jquery": "$"
        },
      }
    }
  }

 

  第四步:去掉编译文件中map文件

    在编译好后,我们会看到文件夹下有特别多的.map文件,这些文件主要是帮助我们线上调试代码,查看样式。所以为了避免部署包过大,通常都不生成这些文件。

    在 config/index.js 文件中将productionSourceMap 的值设置为false. 再次打包就可以看到项目文件中已经没有map文件;

 

 

  第五步--重点:开启gzip压缩(压缩率最高可达70%)

    1. cnpm i compression-webpack-plugin 下载compression-webpack-plugin插件;

 

    2. vue.config.js中添加下面的代码:

configureWebpack: config => {
      return {
        plugins: [
          new CompressionPlugin({
            filename: '[path].gz[query]',
            algorithm: 'gzip',
            // test: /\.js$|\.html$|\.css/, //匹配文件名
            test: /\.(js|css|woff|ttf|json|txt|html|ico|svg)(\?.*)?$/i,
            threshold: 10240, //对超过10k的数据进行压缩
            minRatio: 0.8, // 压缩比小于这个才压缩
            deleteOriginalAssets: false //是否删除源文件
          }),
        ],
        // plugins: plugins,
        externals: { //externals 里的库不会被webpack打包
          'echarts': 'echarts',
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'ElementUI': 'ELEMENT',
          'axios': 'axios',
          'vue-resource': 'VueResource',
          'vuex': 'Vuex',
          'vue-i18n': 'VueI18n',
          "qs": "qs",
          "jquery": "$"
        },
      }
    }

    注意:有些浏览器并不支持.gz文件,因此deleteOriginalAssets: false,就会同时生成.js和.gz文件,只要通过浏览器请求头知道支持.gz文件,那么就自动使用.gz,否则使用.js。

 

    3. 要使服务器返回.gz文件,还需要对服务器进行配置,根据Request Headers的Accept-Encoding标签进行鉴别,如果支持gzip就返回.gz文件,如果后端用SpringBoot ,还需要我们手动开启,在配置文件中添加两行:

server:
  compression:
    enabled: true
    mime-types: application/json,application/xml,text/html,text/plain,text/css,application/x-javascript

   如果后端用的不是SpringBoot,那么可以参考这篇文章来进行配置: https://blog.csdn.net/qq_40999917/article/details/107936750

 

  第六步: 使用阿里巴巴矢量图标库

    我们使用elementUI图标时,往往不能满足项目的要求,有时候产品就要我们使用他们设计的logo,图标等,这个时候如果使用图片或者整合成雪碧图,其实都不太理想,像素可能不够清晰不说,定位、放大失真、加载速度慢或多次请求、同一类型图片颜色不一样就得两个图等等,以上缺点对于网站性能要求高的有时候是致命的!因此这里强烈推荐大家使用阿里巴巴矢量图标库:https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2

    使用步骤一:新建项目

 

 

    使用步骤二:上传.svg图片

 

 

      如果上传失败先检查该svg是不是矢量图做的?如果是图片转为矢量图是不成功的,渐变的svg也是不行,可以看上面六个注意事项,如果都符合但是不成功,可以看我这篇文章: https://www.cnblogs.com/zxd66666/p/13425205.html

 

     使用步骤三:

      1. 在vue-cli项目中引入

 

       2. 注意在iconfont.css加上下面的代码:

[class^="el-icon-bs"], [class*=" el-icon-bs"] {
  font-family:"fontFamily" !important;
  /* 以下内容参照第三方图标库本身的规则 */
  font-size: 18px;
  font-style:normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

 

      3. 在main.js中引入

// 引入icon
import './assets/icon/iconfont.js'
import "./assets/icon/iconfont.css";

    

      4.使用方式

//如果用原本icon颜色
<svg class="icon svg-icon" aria-hidden="true">
    <use href="#el-icon-bs-UnionPay"></use>
</svg>
//如果想要自己设置颜色
<i class="el-icon-arrow-right"></i>

      可以看到这里用法和原先elementUI的icon用法完全一致,我们可以设置font-size改变大小和color改变颜色,完全不会失真!

 

  第七步:Vue SSR

    解决首页js未加载完页面不出来的问题

      1. vue-server-renderer服务端渲染

      2. prerender-spa-plugin客户端的静态页面生成

      3. Nuxt.js 一个vue的服务端渲染框架,容易上手。

    这里的思路无法在于解决vue-cli要在首页加载的时候把js都下载完之后渲染页面的问题,优先渲染页面,让用户不需要一直看空白页,像许多大型网站如京东、淘宝等都是一开始由服务器返回静态页面。参考文章: https://www.jianshu.com/p/0e882b8937a2

    其实我个人是建议可以把public/index.html里面的加载动画写成首页或部分的样子先展示,等到window.onload()加载完毕之后,再移除该dom元素,这要比Vue SSR更好把控,且不需要劳烦后端的同事。

 

其他优化方式

  1. 手动懒加载--较大的图片最后加载,一开始我们给一个空的地址,等到window.onload()之后再替换回去;

  2. 预加载公用数据并放全局--像我公司项目中的卡列表,此时如果不做增删改那么列表数据是不会改变的,而渲染卡列表的子页面可能有好几个,此时我们可以在父组件页的时候就异步获取,然后用sessionStorage保存,如果执行了增删改的方法,成功的时候我们只需要修改本地数据,就无需再次请求后台接口了。但是注意如果用户可以通过其他渠道例如app增删改卡数据,此时还是建议用户每查看一次卡列表就获取一次,不然用户在浏览器打开页面,离开一会的时候在app删除了,回来继续查看发现卡列表没改变,就会引起不必要的投诉了,因此大家注意看项目而定;

  3.  如果不是多个页面而仅仅是两三个页面使用的公用js、css,就在该相关页面单独引用,不要在main.js全局引入;

 

最终效果

 

 

  可以看到了,压缩完之后js体积才351.36KB,快的时候加载速度3.09s,要知道服务器在新加坡,这种速度可以说是惊人的!而第二次再加载因为浏览器有缓存的功能,就只需要1s左右就可以加载完毕,Nice! 

 

网站优化参考文章:

  https://segmentfault.com/a/1190000019499007#articleHeader4

 

另外关于服务器优化方式参考文章:

  http://www.hwsem.com/server/yunzj/201918076.html
  https://www.jianshu.com/p/b358a91bdf2d
  https://jingyan.baidu.com/article/6d704a13c1b3c268da51ca26.html

 

posted on 2020-08-13 19:21  Tom最好的朋友是Jerry  阅读(333)  评论(0编辑  收藏  举报