zoukankan      html  css  js  c++  java
  • 优化国际网站从一分钟到4~6秒

    前言

      前几天开会的时候,被老板质问为何打开网址等了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

  • 相关阅读:
    Setup VSFTPD Server with Virtual Users On CentOS, RHEL, Scientific Linux 6.5/6.4/6.3
    C++ xmmp IM开发笔记(一)
    getting “fatal: not a git repository: '.'” when using post-update hook to execute 'git pull' on another repo
    Bad owner or permissions on .ssh/config
    CentOS6.3安装VBoxAdditions
    仿春雨医生 安卓app(android)
    centos git gitolite安装笔记
    存储过程编译报错如何解决
    冒泡排序
    ORACLE WITH AS 用法
  • 原文地址:https://www.cnblogs.com/zxd66666/p/13498187.html
Copyright © 2011-2022 走看看