精华内容
下载资源
问答
  • 主要介绍了浅谈VUE单页应用首屏加载速度优化方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了vue-cli 首屏加载优化问题,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 特别在移动端,单页面应用的首屏加载优化更是绕不开的话题。下面我会写出我在项目中做的一些优化,希望大家能够相互讨论,共同进步。 我的项目 vue-cli3构建的,vue+vue-router+vuex,UI框架选用 element-ui,ajax...
  • 在Vue项目中,引入到工程中的所有js、css文件,编译时都会被打包进vendor.js,浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多,那么vendor.js文件体积将会相当的大,影响首屏的体验。 这是优化前的页面...
  • 浅谈vue首屏加载优化

    2020-08-27 07:24:52
    主要介绍了浅谈vue首屏加载优化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 本篇文章主要介绍了浅谈Vue SPA 首屏加载优化实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 首屏加载

    2018-08-27 21:00:19
    一个页面的“总加载时间”要比“首屏时间”长,但对于最终用户体验而言,当内容充满首屏的区域时,用户就可以看到网站的主要内容并可以进行相应的操作,所以,首屏时间的快慢,直接影响到用户对网站的认知度 ...

    一、首屏

    以800*600像素尺寸为标准,当浏览器加载页面后看到的第一眼的显示内容为首屏。

    而从开始加载到浏览器页面显示高度达到600像素且此区域有内容显示的时间为首屏显示时间

    二、首屏优化原因

    一个页面的“总加载时间”要比“首屏时间”长,但对于最终用户体验而言,当内容充满首屏的区域时,用户就可以看到网站的主要内容并可以进行相应的操作,所以,首屏时间的快慢,直接影响到用户对网站的认知度

    三、如何优化

    前端缓存和异步加载

    1、css文件

    首页是没有css外链的,这样会再发起多次请求,那么css放在哪里?

    页面切分为模块化加载,对应模块下的css交给js或者jsonp请求返回

    2、js文件

    懒加载:有交互才执行

    3、图片

    图片在非首屏都采用懒加载的模式,这样既能节省流量,也能减少请求数或者延迟请求数

    也可以利用前端性能优化

     

     

     

    展开全文
  • 文章目录前言首屏加载时间的计算首屏的定义首屏加载过程计算首屏时间加载慢的原因面试中常涉及的解决方案减小入口文件体积懒加载减小文件大小静态资源本地缓存UI框架按需加载组件重复打包webpack3webpack4图片懒加载...



    前言

    减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化页面渲染优化

    下面主要简答地介绍一下首屏时间和优化首屏加载的部分做法,面试的时候不用答得很全面,抓住其中最重要的几个点展开就很ok了。

    image-20201219180223913

    首屏加载时间的计算

    首屏的定义

    如图,打开淘宝,页面会逐渐渲染成图3的样子,此时,用户没有任何操作,这里的全部页面就是首屏。

    image-20201219230722623

    用户往下滑,会加载新的商品数据和图片数据,此时,新加载出来的页面,从定义上来说并不是首屏页面。

    说白了,首屏就是,页面打开完成后,第一个可视区域中的所有内容。

    一般来说,用户打开页面后,在1.5秒内完成首屏渲染,能带来较为友好的用户体验,若超过3秒,用户就会容易感到不耐烦,超过5秒,用户流失率就会显著提升。如果网络卡,页面也不应是白屏,应该先加载一部分,并给出加载动画,让用户可以明显感觉到页面正在加载中,因此,我们可以看到,如上图一,商品还未加载出来时,淘宝会先给出页面框架,让用户感到安心,再一步步从图二加载到图三。

    当然,web页面渲染这种事,从来都是越快越好,因此也诞生了PWA(渐进式web app)模式,通过service worker将静态资源install下来,使得网页能像使用app一样。目前,国内的微博、饿了么都已实现,可亲自体验一下(右键install)。

    以上种种,都是各个产品经理大佬和用户心理学大佬经过实践和分析给出来的参考,首屏就是网页给用户的第一印象,要十分重视首屏渲染的优化。

    首屏加载过程

    这是面试极其高频的考题:从输入url到显示网页出来,发生了那些过程

    发生这些过程的所有消耗的时间的总和,就是首屏加载时间。

    大概过程如下:

    1、浏览器的地址栏输入URL并按下回车。

    2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。

    3、DNS解析URL对应的IP。

    4、根据IP建立TCP连接(三次握手)。

    5、HTTP发起请求。

    6、服务器处理请求,浏览器接收HTTP响应。

    7、渲染页面,构建DOM树。

    8、关闭TCP连接(四次挥手)。

    这是侧重从HTTP和TCP/IP层面上来说的,因而忽略了数据链路层和物理层方面的内容。

    计算首屏时间

    常用方法:

    • 首屏模块标签标记法
    • 统计首屏内加载最慢的图片的时间
    • 自定义首屏内容计算法
    • 借助第三方工具(pagespeed、vue-cli等等)

    主要涉及到的api为performance和DOMContentLoaded。

    由于 ReactVue 等框架的出现,DOMContentLoaded 事件已经失去了原本的作用,现在 “首屏渲染时间” 的计算大多数时候是依靠人工打点、performanceAPI和DOM树的MutationObeserver方法(个人了解到的,仅供参考)。

    gtmetrix

    preview

    performance 中的属性如下。

    // 获取 performance 数据
    var performance = {  
        // memory 是非标准属性,只在 Chrome 有
        // 财富问题:我有多少内存
        memory: {
            usedJSHeapSize:  16100000, // JS 对象(包括V8引擎内部对象)占用的内存,一定小于 totalJSHeapSize
            totalJSHeapSize: 35100000, // 可使用的内存
            jsHeapSizeLimit: 793000000 // 内存大小限制
        },
     
        //  哲学问题:我从哪里来?
        navigation: {
            redirectCount: 0, // 如果有重定向的话,页面通过几次重定向跳转而来
            type: 0           // 0   即 TYPE_NAVIGATENEXT 正常进入的页面(非刷新、非重定向等)
                              // 1   即 TYPE_RELOAD       通过 window.location.reload() 刷新的页面
                              // 2   即 TYPE_BACK_FORWARD 通过浏览器的前进后退按钮进入的页面(历史记录)
                              // 255 即 TYPE_UNDEFINED    非以上方式进入的页面
        },
     
        timing: {
            // 在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload 的时间戳,如果无前一个网页 unload ,则与 fetchStart 值相等
            navigationStart: 1441112691935,
     
            // 前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0
            unloadEventStart: 0,
     
            // 和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳
            unloadEventEnd: 0,
     
            // 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0 
            redirectStart: 0,
     
            // 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0 
            redirectEnd: 0,
     
            // 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
            fetchStart: 1441112692155,
     
            // DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
            domainLookupStart: 1441112692155,
     
            // DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
            domainLookupEnd: 1441112692155,
     
            // HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等
            // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间
            connectStart: 1441112692155,
     
            // HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等
            // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间
            // 注意这里握手结束,包括安全连接建立完成、SOCKS 授权通过
            connectEnd: 1441112692155,
     
            // HTTPS 连接开始的时间,如果不是安全连接,则值为 0
            secureConnectionStart: 0,
     
            // HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存
            // 连接错误重连时,这里显示的也是新建立连接的时间
            requestStart: 1441112692158,
     
            // HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
            responseStart: 1441112692686,
     
            // HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
            responseEnd: 1441112692687,
     
            // 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件
            domLoading: 1441112692690,
     
            // 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件
            // 注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源
            domInteractive: 1441112693093,
     
            // DOM 解析完成后,网页内资源加载开始的时间
            // 在 DOMContentLoaded 事件抛出前发生
            domContentLoadedEventStart: 1441112693093,
     
            // DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)
            domContentLoadedEventEnd: 1441112693101,
     
            // DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件
            domComplete: 1441112693214,
     
            // load 事件发送给文档,也即 load 回调函数开始执行的时间
            // 注意如果没有绑定 load 事件,值为 0
            loadEventStart: 1441112693214,
     
            // load 事件的回调函数执行完毕的时间
            loadEventEnd: 1441112693215
     
            // 字母顺序
            // connectEnd: 1441112692155,
            // connectStart: 1441112692155,
            // domComplete: 1441112693214,
            // domContentLoadedEventEnd: 1441112693101,
            // domContentLoadedEventStart: 1441112693093,
            // domInteractive: 1441112693093,
            // domLoading: 1441112692690,
            // domainLookupEnd: 1441112692155,
            // domainLookupStart: 1441112692155,
            // fetchStart: 1441112692155,
            // loadEventEnd: 1441112693215,
            // loadEventStart: 1441112693214,
            // navigationStart: 1441112691935,
            // redirectEnd: 0,
            // redirectStart: 0,
            // requestStart: 1441112692158,
            // responseEnd: 1441112692687,
            // responseStart: 1441112692686,
            // secureConnectionStart: 0,
            // unloadEventEnd: 0,
            // unloadEventStart: 0
        }
    };
    

    1、首屏模块标签标记法

    在HTML文档中对标记首屏内容的结束位置。只适用于不需要通过拉取数据以及不考虑图片等资源加载的情况。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>首屏</title>
      <script type="text/javascript">
        window.pageStartTime = Date.now();
      </script>
      <link rel="stylesheet" href="common.css">
      <link rel="stylesheet" href="page.css">
    </head>
    <body>
      <!-- 首屏可见模块1 -->
      <div class="module-1"></div>
      <!-- 首屏可见模块2 -->
      <div class="module-2"></div>
      <script type="text/javascript">
        window.firstScreen = Date.now();
      </script>
      <!-- 首屏不可见模块3 -->
      <div class="module-3"></div>
        <!-- 首屏不可见模块4 -->
      <div class="module-4"></div>
    </body>
    </html>
    

    首屏时间 = firstScreen- performance.timing.navigationStart

    2、统计首屏内图片完成加载的时间

    通常首屏内容加载最慢的就是图片资源,因此我们会把首屏内加载最慢的图片的时间当做首屏的时间。

    首屏时间 = 加载最慢的图片的时间点 - performance.timing.navigationStart

    3、自定义模块内容计算法

    由于统计首屏图片完成加载的时间比较复杂。因此我们在业务中通常会通过自定义模块内容,来简化首屏时间。如下面的做法:

    • 忽略图片等资源加载情况,只考虑页面主要DOM
    • 只考虑首屏的主要模块,而不是严格意义首屏以上的所有内容。

    加载慢的原因

    在页面渲染的过程,导致加载速度慢的因素可能如下:

    • 网络延时问题
    • 请求资源是否过多
    • 资源文件体积是否过大
    • 资源是否重复发送请求去加载了
    • 加载脚本的时候,渲染内容堵塞了
    • 用户电脑死机,不过这个一般不考虑

    面试中常涉及的解决方案

    由于前端优化的方案有非常多,详细展开会花费很大的篇幅,可以按照这张我做的思维导图来捋一捋各种实现思路。这里只介绍主要的几个面试的切入点,也是平常业务中最常见的。

    image-20201219180223913

    常见的几种SPA首屏优化方式

    • 减小入口文件体积
    • 静态资源本地缓存
    • UI框架按需加载
    • 图片资源的压缩
    • 图片懒加载
    • 组件重复打包
    • 开启GZip压缩
    • 使用SSR,在服务端渲染好一部分数据

    减小入口文件体积

    懒加载

    常用的手段是路由懒加载,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得入口文件变小,加载速度大大增加

    例如,在vue-router配置路由的时候,采用动态加载路由的形式

    routes:[ 
        path: 'index/',
        name: 'Index',
        component: () => import('./views/Index.vue')
    ]
    

    以函数的形式加载路由,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时,才会加载路由组件

    减小文件大小

    在webpack4中,一般是 uglify丑化混淆+tree-shaking。

    概念:1 个模块可能有多个⽅法,只要其中的某个⽅法使⽤到了,则整个⽂件都会被打到 bundle ⾥⾯去,tree shaking 就是只把⽤到的⽅法打⼊ bundle ,没⽤到的⽅法会在 uglify 阶段被擦除掉。

    代码擦除: uglify 阶段删除⽆⽤代码。

    还有很多…这里就不详细介绍下去了。

    静态资源本地缓存

    后端返回资源问题:

    • 前端合理利用localStorage

    • 采用HTTP缓存,设置Cache-ControlLast-ModifiedEtag等响应头(强缓存和弱缓存)

    • 采用Service Worker离线缓存。

      Service Worker有以下几个特点:

      • 独立于主线程、在后台运行的脚本
      • 被install后就永远存在,除非被手动卸载
      • 可编程拦截请求和返回,缓存文件。sw可以通过fetch这个api,来拦截网络和处理网络请求,再配合cacheStorage来实现web页面的缓存管理以及与前端postMessage通信。
      • 不能直接操纵dom:因为sw是个独立于网页运行的脚本,所以在它的运行环境里,不能访问窗口的window以及dom。
      • 必须是https的协议才能使用。不过在本地调试时,在http://localhost 和http://127.0.0.1 下也是可以跑起来的。
      • 异步实现,sw大量使用promise。\
    • 。。。。。。

    UI框架按需加载

    在日常使用UI框架,例如element-UI、或者antd,我们经常性直接引用整个UI

    import ElementUI from 'element-ui'
    Vue.use(ElementUI)
    

    但实际上用到的组件只有按钮,分页,表格,输入与警告,所以我们要按需引用。

    借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。

    import Vue from 'vue';
    import { Button, Select } from 'element-ui';
    import App from './App.vue';
    
    Vue.component(Button.name, Button);
    Vue.component(Select.name, Select);
    /* 或写为
     * Vue.use(Button)
     * Vue.use(Select)
     */
    
    new Vue({
      el: '#app',
      render: h => h(App)
    });
    

    或者也可以这么写

    import Vue from 'vue';
    import {
      Pagination,
      Dialog,
      Autocomplete,
      Dropdown,
    } from 'element-ui';
    
    Vue.use(Pagination);
    Vue.use(Dialog);
    Vue.use(Autocomplete);
    Vue.use(Dropdown);
    
    
    new Vue({
      el: '#app',
      render: h => h(App)
    });
    



    组件重复打包

    假设A.js文件是一个常用的库,现在有多个路由使用了A.js文件,这就造成了重复下载。

    webpack3

    对于之前使用webpack3的项目,多使用CommonsChunkPlugin这个plugin来实现模块的分离。

    CommonsChunkPlugin主要是用来提取第三方库和公共模块,避免首屏加载的bundle文件或者按需加载的bundle文件体积过大,从而导致加载时间过长,是一把优化项目的利器。

    CommonsChunkPlugin提及到chunk主要有以下三种:

    • webpack当中配置的入口文件(entry)是chunk,可以理解为entry chunk
    • 入口文件以及它的依赖文件通过code split (代码分割)出来的也是chunk,可以理解为children chunk
    • 通过commonsChunkPlugin创建出来的文件也是chunk,可以理解为commons chunk

    CommonsChunkPlugin插件可以根据自定义的配置实现各种分离功能,例如:

    • 不分离出第三方库和自定义公共模块
    • 分离出第三方库、自定义公共模块、webpack运行文件
    • 单独分离出第三方库、自定义公共模块、webpack运行文件

    可参考的解决方案:在webpackconfig文件中,修改CommonsChunkPlugin的配置

    minChunks: 3
    

    minChunks为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件

    webpack4

    在webpack4中,CommonsChunkPlugin多被舍弃。

    image-20201218140332243

    webpack4废弃了CommonsChunkPlugin插件,使用optimization.splitChunksoptimization.runtimeChunk来代替,原因可以参考《webpack4:连奏中的进化》一文。

    关于runtimeChunk参数,有的文章说是提取出入口chunk中的runtime部分,形成一个单独的文件,由于这部分不常变化,可以利用缓存。

    splitChunks中默认的代码自动分割要求是下面这样的:

    • node_modules中的模块或其他被重复引用的模块

      就是说如果引用的模块来自node_modules,那么只要它被引用,那么满足其他条件时就可以进行自动分割。否则该模块需要被重复引用才继续判断其他条件。(对应的就是下文配置选项中的minChunks为1或2的场景)

    • 分离前模块最小体积下限(默认30k,可修改)

      30k是官方给出的默认数值,它是可以修改的,上一节中已经讲过,每一次分包对应的都是服务端的性能开销的增加,所以必须要考虑分包的性价比。

    • 对于异步模块,生成的公共模块文件不能超出5个(可修改)

      触发了懒加载模块的下载时,并发请求不能超过5个,对于稍微了解过服务端技术的开发者来说,**【高并发】【压力测试】**这样的关键词应该不会陌生。

    • 对于入口模块,抽离出的公共模块文件不能超出3个(可修改)。也就是说一个入口文件的最大并行请求默认不得超过3个,原因同上。

    splitChunks的在webpack4.0以上版本中的用法是下面这样的:

    module.exports = {
      //...
      optimization: {
        splitChunks: {
          chunks: 'async',//默认只作用于异步模块,为`all`时对所有模块生效,`initial`对同步模块有效
          minSize: 30000,//合并前模块文件的体积
          minChunks: 1,//最少被引用次数
          maxAsyncRequests: 5,
          maxInitialRequests: 3,
          automaticNameDelimiter: '~',//自动命名连接符
          cacheGroups: {
            vendors: {
              test: /[\\/]node_modules[\\/]/,
              minChunks:1,//敲黑板
              priority: -10//优先级更高
            },
            default: {
              test: /[\\/]src[\\/]js[\\/]/
              minChunks: 2,//一般为非第三方公共模块
              priority: -20,
              reuseExistingChunk: true
            }
          },
          runtimeChunk:{
              name:'manifest'
          }
        }
      }
    

    图片懒加载

    这个很好理解,图片只在准备下滑到其区域时,才发送请求加载图片。

    img



    图片资源的压缩

    图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素

    webpack 在处理图片的时候,会涉及一下几个问题:

    • 图片的大小问题,比如是否压缩图片,限制图片大小
    • 图片引用方式的问题,是用base64 的格式引用图片,还是用url 路径引用图片
    • 图片路径问题,开发时写的图片路径和发布时的图片路径不同

    跟图片路径有关的文件主要有一下几类:

    • css 里的background-image
    • html 里的<img>标签:模板文件里的<img>标签、主页面的<img>标签
    • js 里引入的img

    webpack处理图片常用依赖

    • file-loader:在css 和html 主页中,相对路径的图片都会被处理,发布到输出目录中

    • url-loader:是对file-loader的封装,因此在安装了file-loader和url-loader 后,在webpack.config.js 中只对url-loader 做配置即可。url-loader的自身功能是给图片一个limit 标准,当图片小于limit时,使用base64 的格式引用图片;否则,使用url 路径引用图片。

    • image-webpack-loader:压缩图片。这个用得不算太多,因为前期可以直接让UI设计把图片压缩好,像ps 就可以自动的批量压缩图片。

    • 对于所有的图片资源,我们可以进行适当的压缩。

    webpack打包时,会根据webpack.config.jsurl-loader中设置的limit大小来对图片进行处理,小于limit的图片转化成base64格式,其余的不做操作。对于比较大的图片我们可以用image-webpack-loader 来压缩图片。

    npm install image-webpack-loader --save-dev
    

    webpack.config.js 中配置:

    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      use:[
        {
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
          }
        },
        {
          loader: 'image-webpack-loader',// 压缩图片
          options: {
            bypassOnDebug: true,
          }
        }
      ]
    }
    
    • 使用icon等在线字体和雪碧图

    对页面上使用到的icon,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻http请求压力。



    开启GZip压缩

    clipboard.png

    拆完包之后,我们再用gzip做一下压缩 安装compression-webpack-plugin

    nmp i compression-webpack-plugin -D
    

    vue.congig.js中引入并修改webpack配置

    const CompressionPlugin = require('compression-webpack-plugin')
    
    configureWebpack: (config) => {
            if (process.env.NODE_ENV === 'production') {
                // 为生产环境修改配置...
                config.mode = 'production'
                return {
                    plugins: [new CompressionPlugin({
                        test: /\.js$|\.html$|\.css/, //匹配文件名
                        threshold: 10240, //对超过10k的数据进行压缩
                        deleteOriginalAssets: false //是否删除原文件
                    })]
                }
            }
    

    在服务器我们也要做相应的配置 如果发送请求的浏览器支持gzip,就发送给它gzip格式的文件 。

    express框架搭建的只要安装一下compression就能使用

    const compression = require('compression')
    app.use(compression())  // 在其他中间件使用之前调用
    

    这是基本用法,如果还要对请求进行过滤的话,还要加上

    app.use(compression({filter: shouldCompress}))
    
    function shouldCompress (req, res) {
      if (req.headers['x-no-compression']) {
        // 这里就过滤掉了请求头包含'x-no-compression'
        return false
      }
    
      return compression.filter(req, res)
    }
    

    如果用的是koa,用法和上面的差不多

    const compress = require('koa-compress');
    const app = module.exports = new Koa();
    app.use(compress());
    

    因为node读取的是生成目录中的文件,所以要先用webpack等其他工具进行压缩成gzip,webpack的配置如下

    const CompressionWebpackPlugin = require('compression-webpack-plugin');
    plugins.push(
        new CompressionWebpackPlugin({
            asset: '[path].gz[query]',// 目标文件名
            algorithm: 'gzip',// 使用gzip压缩
            test: new RegExp(
                '\\.(js|css)$' // 压缩 js 与 css
            ),
            threshold: 10240,// 资源文件大于10240B=10kB时会被压缩
            minRatio: 0.8 // 最小压缩比达到0.8时才会被压缩
        })
    );
    

    webpack+node的gzip打包初步就介绍到这里,更多用法请移步compression文档:https://github.com/expressjs/compression



    合理使用Web Worker

    可以理解为主线程的一个协程。

    众所周知,JavaScript是单线程的,但是碰到一些计算密集型或者高延迟的任务时,会影响整个页面的运行。Web Worker就是在这个环境下诞生的,它也是HTML5的新特性之一。

    Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
    Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
    引用自阮一峰老师的文章《Web Worker 使用教程》

    使用例子:首屏上使用了async/await或者长达1秒的动画,可能会阻塞到主线程,那么可以使用Web Worker等技术来实现时间分片,将大任务拆分成许多个小任务,使得主线程能抽出空来渲染页面,降低卡顿感。

    使用SSR

    SSR(server side render),也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器。

    SSR技术会实现将指定的异步数据在服务端渲染好,再返回给客户端,这样就减轻了客户端的请求异步数据的压力,渲染页面就更快了。

    • vue可使用Nuxt.js框架实现服务端渲染
    • react多采用koa2等技术的实现方案。

    图片描述

    image-20201219152301095

    结语

    目前就暂时介绍这么多,还有很多优化方案,可以参考文中的思维导图来稍作总结。

    参考

    https://www.cnblogs.com/dashnowords/p/9545482.html

    https://cloud.tencent.com/developer/article/1650697

    https://github.com/expressjs/compression

    《前端性能测试–Performance API》https://zhuanlan.zhihu.com/p/43746227

    《原生js实现图片懒加载(lazyLoad)》https://zhuanlan.zhihu.com/p/55311726

    展开全文
  • 1、路由懒加载。 原来的路由引入组件 import Index from @/views/index.vue; { path: '/' name: 'index' component: Index } 现在引入路由(vue异步组件) import Vue from 'vue'; import Router from 'vue-router...

    执行npm run build,将打包代码部署上线后访问项目,会发现表现很糟糕,页面会出现长时间的空白等待,这是无法忍受的性能问题,迫切需要解决。

    1、路由懒加载。

    原来的路由引入组件

    import Index from @/views/index.vue;
    {
    	path: '/'
    	name: 'index'
    	component: Index
    }
    

    现在引入路由(vue异步组件)

    import Vue from 'vue';
    import Router from 'vue-router';
    Vue.use(Router)
     {
          path: "/",
          name: "index",
          component: resolve => require(["@/views/Index"], resolve)
    }
    

    ES 提出的import方法(常用)
    const HelloWorld = ()=>import(‘需要加载的模块地址’)

    import Vue from 'vue';
    import Router from 'vue-router';
    Vue.use(Router)
    const HelloWorld = ()=>import("@/components/HelloWorld")
    export default new Router({
      routes: [
        {
          path: '/',
          name: 'HelloWorld',
          component:HelloWorld
        }
      ]
    })
    

    2.组件懒加载

    原来组件中的写法:

    <template>
    	<div>
    		<span></span>
    		<One-com></One-com>
    	</div>
    </template>
    
    <script>
    import One from './one';
    export default{
    	components:{
    		"One-com": One,
    	},
    	data(){
    		return{
    			num: 0
    		}
    	}
    }
    </script>
    
    

    const 方法

    <template>
      <div class="hello">
      <One-com></One-com>
      1111
      </div>
    </template>
    
    <script>
    const One = ()=>import("./one");
    export default {
      components:{
        "One-com":One
      },
      data () {
        return {
          msg: 'Welcome to Your Vue.js App'
        }
      }
    }
    </script>
    

    异步方法:

    <template>
      <div class="hello">
      <One-com></One-com>
      1111
      </div>
    </template>
    
    <script>
    export default {
      components:{
        "One-com":resolve=>(['./one'],resolve)
      },
      data () {
        return {
          msg: 'Welcome to Your Vue.js App'
        }
      }
    }
    </script>
    

    3.服务器开启gzip。此步的优化效果最显著

    第1步 先在vue-config.js中配置开启gzip。

    // 安装插件
    npm i --save-dev compression-webpack-plugin
     
    // 在vue-config.js 中加入
    const CompressionWebpackPlugin = require('compression-webpack-plugin');
    const productionGzipExtensions = ['js', 'css'];
    const isProduction = process.env.NODE_ENV === 'production';
     
    .....
    module.exports = {
    ....
     configureWebpack: config => {
      if (isProduction) {
       config.plugins.push(new CompressionWebpackPlugin({
        algorithm: 'gzip',
        test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
        threshold: 10240,
        minRatio: 0.8
       }))
      }
     }
    }
    

    第2步 WEB服务器开启gzip。这里以我的nginx为例。

    gzip  on;
    gzip_types text/plain application/x-javascript application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    

    4.启用cdn加速。

    用Gzip已把文件的大小减少了三分之二了。如果还不能满足,把那些不太可能改动的代码或者库分离出来,继续减小单个chunk-vendors,然后通过CDN进行加速加载资源。
    (对vue、vuex、vue-router、vue-moment采用cdn引入,此外客户端还可以引入highlight的cdn,但管理端不需要。因此,需要两份不同的模板html,配置分别如下:)

    (1)、vue.config.js 在上一步的基础上继续加入

    config.externals的配置,如下:
    configureWebpack: config => {
        if (isProduction) {
          config.plugins.push(
            new CompressionWebpackPlugin({
              algorithm: "gzip",
              test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
              threshold: 10240,
              minRatio: 0.8
            })
          );
     
          config.externals = {
            vue: "Vue",
            "vue-router": "VueRouter"
          };
        }
      }
    

    (2)、在原来所有引入vue、vue-router的地方,全部屏蔽或删除。

    //原来对vue、vue-router的引用全部注释掉。
    //涉及所有引用的文件,只要有引入就注释掉。
     
    // import Vue from "vue";
    // import Router from "vue-router";
     
    //vue-router的非cdn引用
    //Vue.use(Router);
     
    

    (3)、在代码中用vue-router的时候,用VueRouter。

    //cdn 引入vue-router时,源码抛出的变量是:VueRouter
    console.log(VueRouter);
    Vue.use(VueRouter);
     
    //Vue.use(Router); 继续像原来一样用Router就会报错。
    

    预渲染

    以上方案解决的问题是缩小js资源体积以便加快加载速度,这样的方案在网络良好的情况下首屏渲染的速度已经够快了,但是终归讲,渲染依赖于js加载完成后的执行逻辑,而且这样的方式不利于SEO。那么进一步提高首屏加载的方案还有两个,一个是预渲染,一个是SSR,即服务端渲染,后者的方案较为复杂,我会在以后的文章中进行分析,服务端渲染的方式相比预渲染,最主要的优势是可以动态拼接数据,作为文档的一部分返回,从而实现更友好的SEO和动态分享等功能。

    预渲染依赖一个prerender-spa-plugin插件,首先要在webpack.prod.conf.js中引入该插件,如下

    const PrerenderSPAPlugin = require('prerender-spa-plugin')
    

    然后,在plugins中添加以下插件配置:

    new PrerenderSPAPlugin(
    
          path.join(__dirname, '../nginx/blog'),
          ['/'],
          {
            //在一定时间后再捕获页面信息,使得页面数据信息加载完成
              captureAfterTime: 50000,
              //忽略打包错误
              ignoreJSErrors: true,
              phantomOptions: '--web-security=false',
              maxAttempts: 10,
            }
    )
    

    经过这样配置以后,打包生成的index.html就包含了预渲染的dom结构,因此首屏渲染速度会得到更大提升。但是这里要注意一个问题,异步加载的路由打包后的chunk文件被插入了head标签中,并且带有一个async属性,如下:

    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      <title>Blog - SilentPort</title>
      <link href="/static/css/client.6b5a982c3673872dbaa1a8891279d36d.css" rel="stylesheet">
      <script type="text/javascript" charset="utf-8" async="" src="/static/js/3.c925dfc72043d1d1d5ac.js"></script>
    </head>
    

    而运行时的manifest文件则位于body的底部,由于async会导致加载和渲染后续文档元素的过程和当前script脚本的加载与执行并行进行(异步),因此会导致该script脚本先于manifest执行,这会产生一个webpackJsonp is not defined错误。因此在部署之前这里需要手动将async改成defer,后者在加载后续文档元素的过程中也会和当前script脚本的加载并行进行(异步),但是当前script脚本的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成,这样就保证了脚本后于manifest执行。

    参考文章:https://www.jianshu.com/p/da46f410156a?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    展开全文
  • vue 项目首屏加载性能调优

    千次阅读 热门讨论 2020-12-09 00:44:38
    () => import('../views/router/optimization') } 有同学提出问题,为什么配置了路由懒加载之后,依旧是在首屏加载时加载所有的资源信息,那路由懒加载的作用是什么? 首先要明确的是配置路由懒加载后确实是生效了...

    体积性能优化 项目地址

    最近发现项目在github上启动速度达到恐怖的 8 秒,在gitee的启动速度也很慢,3.04 秒,首页动画是通过 CDN 加载进来的,所以没有算在内,github8秒,国外吧,那也没啥好说的

    但是gitee的启动速度 3.04 秒

    不得了,我强迫症犯了,就好比有人在我的耳边对我说:这个世界上根本没有奥特曼!!!

    难受,淦 o(゚Д゚)っ!

    本来想着项目在github/gitee上部署后,这两个网站都自带GZIP压缩了,所以打包时就用了最原始的打包方式,方便其他同学根据自己的需求自定义打包配置。好家伙,咩想到这么慢。

    直接定位问题,然后顺便把体积性能优化的过程也写出来吧。

    定位问题

    在 v1.0.1 beta 版本中发现路由组件懒加载无效,导致chunk-vendors文件大小达到 5M,同时quasar体积达到 1M

    问题原因出在用来做嵌套路由布局的 layout组件上,当时layout组件不是懒加载的,是在路由声明时一次性加载完成,同时它还把本该懒加载的组件都加载进来了,因此导致体积过大。

    分析项目体积可以使用webpackwebpack-bundle-analyzer或是 VUE GUI 里自带的webpack Analyzer

    使用webpack-bundle-analyzer分析结果如下:

    chunk-vendors.jsechartsquasar
    5.05 MB(路由懒加载失败 )2 MB (没有按需引入)1MB(路由懒加载失败)

    在这里插入图片描述

    找到问题后使用通用的优化方法进行优化,常规的性能优化一般有五种:

    1. 单组件 / UI 组件按需引入
    2. 路由懒加载
    3. 通过 CDN 获取资源,而不是将资源打包到项目中
    4. 关闭sourcemap文件打包
    5. Gzip 压缩项目资源
    6. 对于字体等体积较大的静态资源,开启浏览器缓存

    1、按需引入

    按需引入就是在开发的时候只引入需要的组件,而不是一次性将所有不需要的 UI 组件都引入进来,最常见的就是 UI 框架组件按需引入,比如我只需要Dialog组件,那我就只引如Dialog组件即可。

    对于quasar按需引入的格式一般如下:

    import {
      Quasar,
      LoadingBar,
      Dialog,
      ......
    } from 'quasar'
    
    Vue.use(Quasar,
    {
      ......
      plugins: {
        LoadingBar,
        Dialog,
      ......
      }
    })
    

    同时各个依赖都有自己按需引入的方法,比如echarts按需引入如下:

    import ECharts from 'vue-echarts'
    
    // 手动引入 ECharts 各模块来减小打包体积
    import 'echarts/lib/chart/bar'
    import 'echarts/lib/component/tooltip'
    import 'echarts/lib/chart/line'
    import 'echarts/lib/component/polar'
    import 'echarts/lib/chart/pie'
    
    // 注册 ECharts
    Vue.component('v-chart', ECharts)
    

    2、路由懒加载:

    路由懒加载目前比较常用的格式如下(当然还有很多种格式,需要请自行百度):

    {
      path: 'optimization',
      name: 'optimization',
      meta: {},
      component: () => import('../views/router/optimization')
    }
    

    有同学提出问题,为什么配置了路由懒加载之后,依旧是在首屏加载时加载所有的资源信息,那路由懒加载的作用是什么?

    首先要明确的是配置路由懒加载后确实是生效了的,只不过 vue 默认为所有被懒加载的路由使用了 prefetch(预先加载模块),提前获取用户未来可能会访问的内容,因此才会将路由懒加载的文件一股脑加载进来。

    vue 官网路由懒加载中提到,路由懒加载的作用是将不同的路由打包在不同的块(chunk_xxxxxxx.js)中,而原本默认是将路由都打包在 main (chunk-vendors.js)里,这样做能通过将懒加载的路由从 main 中分割出来,从而减少 main 的体积。
    当然你也可以指定某几个路由打包成一个chunk文件:

    比如:通过内联注释的方式,将下面三个路由打包成 group-foo.js 文件

    const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
    const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
    const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
    

    chunk-vendors.js加载之后,其他配置了路由懒加载的页面基本不会影响首屏加载的速度。

    当然比如在移动端或对流量比较敏感的场景,我们也可以将默认的 prefetch(预先加载模块) 关闭。vue 官网给出了关闭方法 Prefetch

    // vue.config.js
    module.exports = {
      chainWebpack: config => {
        // 移除 prefetch 插件
        config.plugins.delete('prefetch')
    
        // 或者
        // 修改它的选项:
        config.plugin('prefetch').tap(options => {
          options[0].fileBlacklist = options[0].fileBlacklist || []
          options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
          return options
        })
      }
    }
    

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

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

    对于 prefetch 和 Preload 的详细使用,可以参考下面这篇文章,里边还提供了一些最佳实践的场景分享:

    使用 Preload&Prefetch 优化前端页面的资源加载 BY: vivo互联网技术

    3、通过 CDN 获取资源

    比如echarts使用 CDN 资源引入(项目中对echarts配置了按需加载)

    index.html文件中添加资源标签

    <script src="https://cdn.bootcss.com/echarts/3.7.0/echarts.min.js"></script>
    

    vue.config.js中做配置,告诉Webpack打包时echarts是外部引入的

    module.exports = {
      configureWebpack: {
        externals: {
          echarts : 'echarts' // 不影响在项目中使用 import 引入 echarts
        }
      }
    }
    

    CDN 不只能用在引入外部 js 资源,如果有 json 或 md 数据,也可以把它当做一个 OOS 使用。甚至是创建自己的 CDN 服务器为自己服务,如果你对自己的服务器没有信心的话。

    4、关闭sourcemap文件打包

    打包后生成的sourcemap文件的主要用来处理chunk文件映射,这样你的程序到生产环境运行时报错还能找到源码对应的位置,但既然是生产环境了,sourcemap文件也没啥用了

    module.exports = {
      ......
      // 关闭 sourcemap
      productionSourceMap: false,
      ......
    }
    

    5、使用Gzip压缩文件

    Gzip是默认绝大部分浏览器都支持的文件格式,Gzip能将默认打包生成的大文件压缩成小文件,从而提高项目的响应速度。

    首先需要引入WebpackGzip压缩插件,在package.json中插入

    "compression-webpack-plugin": "^1.1.12"
    或
    npm i compression-webpack-plugin@1.1.12 --save-dev
    

    :::tip
    别用太高版本的compression-webpack-plugin,会出现未知错误,本人深受其害,当时默认npm安装最新版,好家伙,花我半天去找问题。
    :::

    vue.config.js中配置压缩规则:

    module.exports = {
      ......
      // Webpack 函数式配置
      configureWebpack: config => {
        // 生产环境配置
        if (process.env.NODE_ENV === 'production') {
        
          // 消除 console 输出信息
          config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
    
          // Gzip 压缩
          const CompressionPlugin = require('compression-webpack-plugin')
          config.plugins.push(
            new CompressionPlugin({
              algorithm: 'gzip',  // 
              test: /\.(js|css|woff|woff2|svg)$/, // 哪些文件会被压缩
              threshold: 10240, // 对超过10k的数据压缩
              deleteOriginalAssets: false, // 不删除压缩前的文件,如果浏览器不支持 Gzip ,则会加载源文件
              minRatio: 0.8 // 压缩比大于 0.8 的文件将不会被压缩
            })
          )
    
          // 将 js 文件夹添加时间戳,这样浏览器不会加载上个版本缓存的代码
          config.output.filename = `js/[name].${timeStamp}.js`
          config.output.chunkFilename = `js/[name].${timeStamp}.js`
          
        } else {
          // 开发环境配置
        }
      },
      ......
    }
    

    配置Gzip压缩之后,需要你的服务器支持Gzip格式文件(浏览器支持,服务器不一定默认支持)

    我用的比较多的是Nginxexpresstomcat,因此只列出这些服务器的配置方式,其他服务器都是异曲同工

    Nginx 开启Gzip支持

    conf/nginx.conf中添加如下配置

     server {
       ......
    	# 开启gzip
    	gzip on;
    		
    	# 压缩的文件类型(如果没有你需要的类型,可以去 mime.types 里查看,然后复制过来)
    	gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
    		
    	# 是否在 http header 中添加 Vary: Accept-Encoding 建议开启
    	gzip_vary on;
    	 ......
    }
    

    对于gzip_types的配置项,可以在mime.types文件里找到对应的类型,mime.types可以把它当做是浏览器支持的格式声明,因此修改就算其中的类型值,也是无用的

    :::tip
    我在做某个项目时,压缩了ttf文件,然而在mime.types文件没有发现ttf格式文件的支持类型,看了一下浏览器中对于ttf格式的类型是Content-Type: application/x-font-ttf,因此ttf压缩后的Gzip文件在服务器中并没有生效。
    网络上虽然有Ngnix使用Gzipttf压缩痕迹,但是都是一笔带过。还是自己太菜了…
    :::

    Express 开启Gzip支持

    安装对应依赖

    npm install compression --save
    

    app.js中启用

    var compression = require('compression')
    var app = express()
    // 启用gzip
    app.use(compression())
    

    Tomcat 开启Gzip支持

    修改 tomcat 8 的 server.xml,找到默认端口的位置,在后面添加配置如下

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"
    	compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla,traviata" 
    	compressableMimeType="text/html,text/xml,text/css,application/javascript,text/plain"/>
    

    体积性能优化后的结果

    未优化优化后Gzip 压缩后
    chunk-vendors.js5.05 MB2.66 MB350 KB
    echarts2 MB1.08 MB90.4 KB
    quasar1MB294.62 KB44.39 KB

    在这里插入图片描述

    这一次的性能优化到这就结束了,来看看效果

    优化前优化后
    Github8s 左右3.5s 左右
    Gitee3s 左右1s 左右

    这是 v1.0.1 beta 版本的在Gitee上的访问速度,减去首屏动画 CDN 下载的耗时,速度在 3s 左右
    在这里插入图片描述
    性能优化后在Gitee上访问的速度:

    在这里插入图片描述
    可以看到响应时间从 3.76 s 提升到了 1.073 s (减去首屏动画 CDN 下载的耗时)

    性能优化后在Github上的访问速度

    在这里插入图片描述
    可以看到响应时间从 8 s 提升到了 3.57 s

    在我自己的 Express 部署,然后 Ngnix 转发后的速度,减去首屏动画 CDN 下载的耗时 167 ms,优化后的速度为 347 ms
    在这里插入图片描述

    那天我拿着手电筒对着电视照亮迪迦奥特曼的能量指示器,助他战胜基里艾洛德星人 ┗( ▔, ▔ )┛

    我,也变成了光 ~ ~

    展开全文
  • vue实现首屏加载等待动画

    千次阅读 2020-06-17 17:13:09
    vue实现首屏加载等待动画 vue实现首屏加载等待动画 避免首次加载白屏尴尬 hua 不多说直接上代码 直接修改index.html // An highlighted block <!DOCTYPE html> <html lang="en"> <head> <...
  • 我实际的项目首屏加载从 12s 左右优化到 4s 左右。由于是演示项目,并没有开发其他的页面和功能,效果不是很明显,大家可以自行踩坑。大家有更好的方案,可以共同学习! 我们以 vue-cli 工具为例,使用 vue-router ...
  • vue首屏加载优化总结及整理

    千次阅读 2020-06-28 16:21:41
    基于vue的页面加载优化详谈,主要列举了部分优化的点,包括客户端以及服务端
  • 在优化之后 首屏加载速度在1.2秒左右,当然还有优化空间,后期还可以考虑做个骨架屏,loading什么的提高用户体验 优化方案 优化之前下载webpack-bundle-analyzer webpack-bundle-analyzer 是 webpack的可视化资源...
  • 1.异步路由加载 import Vue from 'vue' import Router from 'vue-router' // 之前的方案 // import Index from '@/pages/index/' // import ChooseUser from '@/pages/detail/chooseUser' // 异步加载方案 const...
  • vue 首屏加载慢的问题

    2020-07-16 11:18:37
    项目遇到的问题总结(四):单页面首屏加载慢解决方案 VUE 单页应用首页加载特别慢的解决方法,(我自己没百度之前,想的是路由懒加载,图片懒加载,压缩cssjs) 百度之后,才发现菜鸡 我们一般打包后把 生成的...
  • 优化首屏加载速度

    2020-06-23 09:55:10
    为给客户更好的客户体验,首屏组件加载速度更快一些,解决白屏问题。 二、定义 懒加载简单来说就是延迟加载或按需加载,即在需要的时候的时候进行加载。 三、使用 常用的懒加载方式有两种:即使用vue异步组件 和 ES...
  • 1. 首先打包后看看加载时间 令人窒息的36.1s 先从简单的开始吧,压缩下static下的图片资源: 清除浏览器缓存 可以看到,差别其实不大, 2. vendor 参考博文:关于vue 项目页面打包后首次页面加载特别缓慢的原因及...
  • Vue 首屏加载速度优化-这篇就够了

    万次阅读 2019-06-22 18:17:54
    Vue-cli上线首屏加载优化记 vue项目首页加载速度慢的有效优化1.影响加载速度的原因2.分析文件大的原因利用webpack-bundle-analyzer 分析器,分析项目依赖关系3.项目依赖优化---插入链接与图片如何插入一段漂亮的代码...
  • vue首屏加载

    千次阅读 2019-07-15 20:21:06
    如果没有这个设置,项目首屏加载时会加载整个网站所有的JS文件,所以将JS文件拆开,点击某个页面时再加载该页面的JS是一个很好的优化方法。 这里用到的就是vue的组件懒加载。在router.js中,不要使用import的方法...
  • 一、什么是首屏加载首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前...
  • H5 分包实现首屏加载时间优化H5 分包实现首屏加载时间优化一、为什么首屏加载需要优化二、分析产物三、分包实现四、解析 splitChunks H5 分包实现首屏加载时间优化 一、为什么首屏加载需要优化 因为做了很多事情: ...
  • 很多网页首屏加载速度很慢我下面用了一些处理方法供大家参考 1.使用路由的懒加载 //咱们平时在router.js中引入各个组件方式 import newIndex from '@/components/newIndex' import newRole from '@/components/new...
  • vue-cli3首屏加载优化

    千次阅读 2019-05-16 17:55:51
    首屏加载优化 项目基于vue2.x+vue-router + vuex + element-ui 结合 vue-cli3.0 背景和结果:项目上线完首屏加载比较慢,加载时间为11s+,优化之后加载时间控制在4s左右,打包体积从原来的5.76M变为2.54M。 优化方向...
  • Vue:首屏加载页实现

    2020-08-19 15:44:31
    众所周知vue项目通常首屏加载会非常慢,在浏览器加载资源时,可以在首屏加入一个loading页面。 首先找到在根目录下的 /pulic/index.html: 在 index.html 中找到我们的id为app的div元素: 示例修改如下: <!-- ...
  • VUE 首屏加载时间优化

    2019-05-13 11:03:07
    在Vue项目中,引入到工程中的所有js、css文件,编译时都会被打包进vendor.js,浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多,那么vendor.js文件体积将会相当的大,影响首屏的体验。 解决方法是,将...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,195
精华内容 16,478
关键字:

首屏加载