Vue单页应用首次加载太慢之性能优化

 

问题描述:

 

最近开发了一个单页应用,上线后发现页面初始加载要20s才能完成,这就很影响用户体验了,于是分析原因,发现页面加载时有个 vendor.js达到了3000多kb,于是在网上查找了一下原因,是因为我打包的时候把所有第三方依赖都打包放进去了;要怎么分离出去呢?

 

看下面步骤:

 

一、解决打包后vendor.js 很大,导致上线后页面首次加载速度异常慢:

vue-cli npm run build命令默认把dependencies中的依赖统一打包,导致vendor.js文件过大,出现首屏加载过于缓慢的问题。

解决方案:使用externals引用第三方资源,防止element资源被打包到自己项目中,(总共修改3个部分index.html、webpack.base.conf.js、main.js)

 

1、修改index.html页面,在head中引入cdn上的资源。

<!-- 正常的引入 cdn 资源即可 -->

<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/element-ui/2.4.0/index.js"></script>
<script src="https://cdn.bootcss.com/echarts/3.7.0/echarts.min.js"></script>

注意:上面是直接重cdn上引入的,如果某个时候cdn服务器出现问题,我们的项目就瘫痪了,所以为了安全起见要给自己留一手喔。

采用下面的方法,当上面的文件引入失败后,就从备用的地址引入;当然备用的地址你也可以换成本地的,我这里是放的另一个cdn服务器上的,

应该不会两个服务器同时出现故障吧!...

<!-- 引入 cdn 资源 -->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<script>
  //<![CDATA[
  if (typeof Vue == 'undefined') {
    document.write(unescape("%3Cscript src='https://cdn.staticfile.org/vue/2.6.10/vue.min.js' %3E%3C/script%3E"));
  } //]]>
</script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script>
  //<![CDATA[
  if (typeof VueRouter == 'undefined') {
    document.write(unescape("%3Cscript src='https://cdn.staticfile.org/vue-router/3.0.7/vue-router.min.js' %3E%3C/script%3E"));
  } //]]>
</script>
<script src="https://cdn.bootcss.com/element-ui/2.4.0/index.js"></script>
<script>
  //<![CDATA[
  if (typeof ELEMENT == 'undefined') {
    document.write(unescape("%3Cscript src='https://cdn.staticfile.org/element-ui/2.10.1/index.js' %3E%3C/script%3E"));
  } //]]>
</script>
<script src="https://cdn.bootcss.com/echarts/3.7.0/echarts.min.js"></script>
<script>
  //<![CDATA[
  if (typeof echarts == 'undefined') {
    document.write(unescape("%3Cscript src='https://cdn.staticfile.org/echarts/4.2.1-rc1/echarts-en.min.js' %3E%3C/script%3E"));
  } //]]>
</script>

 

2、修改webpack.base.conf.js文件.添加externals配置

externals: {
  'vue': 'Vue',
  'vue-router': 'VueRouter',
  'element-ui': 'ELEMENT',
  "echarts": "echarts",

},

 

3. 删除main.js中的相应import from。因为如果不删除,打包的时候还会把这两个文件打进去。

最后去打包,发现vendor.js只有300kb了。上线后发现页面首次加载飞快了。

 

下面再补充一些其它优化:

 

1、路由懒加载肯定是要做的:

当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,

然后当路由被访问的时候才加载对应组件,这样就更加高效了。结合 Vue 的异步组件和 Webpack 的代码分割功能

轻松实现路由组件的懒加载。具体实现方法官网和网上有很多例子,这里就不详细讲解了。

 

2、本地图片与请求的后台图片的大小:

在我这个项目中有很多图片,最开始没太在意图片的大小,导致上线后很多大的图片加载很慢,于是我把图片做了压缩处理;推荐个网站:http://www.bejson.com/ui/compress_img/(压缩图片不失帧);

当然我们也可以使用webpack里的插件对打包的图片进行压缩,也可以使用gulp.js里的插件对图片进行压缩。具体自己去百度吧...

 

3、打包后app.css过大:

我们可以把app.css做拆分,可以利用 webpack 中的 dll 做一部分的分割,比如第三方等的公用 css 文件。

然后再者可以利用 mini-css-extract-plugin 这个插件做各自模块的 css 文件提取(如果用的是webpack4),

webpack3 的化可以用 extract-text-webpack-plugin。

 


 

参考文章

 

Vue 项目首次打开时加载速度很慢的优化方案

 

懒加载

使用 vue-router 懒加载解决首次加载时资源过多导致的速度缓慢问题
当你的 SPA(单页应用程序)变得很复杂时,打包构建后的 js 包会变得非常大,以至于严重影响页面的加载时间。vue-router 支持 webpack 内置的异步模块加载系统。所以,那些使用较少的路由组件不必打包进 bundles 里,只要在路由被访问时按需加载。
懒加载路由写法:

{
    path: "/base/user",
    name: "user",
    component: resolve => require.ensure([], () => resolve(require('@/modules/base/user/User')), 'User'),
    meta: {
        breadcrumb: ["基本信息", "用户管理"]
    }
},
{
    path: "/base/role",
    name: "role",
    component: resolve => require.ensure([], () => resolve(require('@/modules/base/role/Role')), 'Role'),
    meta: {
        breadcrumb: ["基本信息", "角色管理"]
    }
}



使用CDN加速

以引入vue、vuex、vue-router为例:


第一步,在index.html中,添加CDN资源:

<!-- 引入Vue.js -->
<script src="https://cdn.staticfile.org/vue/2.4.3/vue.min.js"></script>
<!-- 引入vuex.js -->
<script src="https://cdn.staticfile.org/vuex/3.0.0/vuex.min.js"></script>
<!-- 引入vue-router -->
<script src="https://cdn.staticfile.org/vue-router/3.0.0/vue-router.min.js"></script>


第二步,在 bulid/webpack.base.conf.js 文件中,增加 externals,将引用的外部模块导入,如下:

 

第三步,将所有的引用去掉:

// import Vue from "vue";
// 引入element 组件
// import ElementUI from "element-ui";
// import "element-ui/lib/theme-chalk/index.css";
// import VueRouter from "vue-router";
// import Vuex from "vuex";

// Vue.use(ElementUI);
// Vue.use(VueRouter);
// Vue.use(Vuex);


参考链接:https://blog.csdn.net/LonewoIf/article/details/87775105

 


 

浅谈VUE单页应用首屏加载速度优化方案

 

这篇文章主要介绍了浅谈VUE单页应用首屏加载速度优化方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

 

单页应用会随着项目越大,导致首屏加载速度很慢!!!以下给出在下知道的几种优化方案

  • 使用CDN资源,减小服务器带宽压力
  • 路由懒加载
  • 将一些静态js css放到其他地方(如OSS),减小服务器压力
  • 按需加载三方资源,如iview,建议按需引入iview中的组件
  • 使用nginx开启gzip减小网络传输的流量大小
  • webpack开启gzip压缩
  • 若首屏为登录页,可以做成多入口,登录页单独分离为一个入口

 

使用CDN资源,减小服务器带宽压力

在index.html中引入cdn资源

1

2

3

4

5

6

7

8

9

10

11

...

 <body>

  <div id="app">

  </div>

  <!-- built files will be auto injected -->

  <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>

  <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>

  <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>

  <script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script>

 </body>

 ...

修改 build/webpack.base.conf.js

1

2

3

4

5

6

7

8

9

10

11

12

13

module.exports = {

 context: path.resolve(__dirname, '../'),

 entry: {

  app: './src/main.js'

 },

 externals:{

  'vue': 'Vue',

  'vue-router': 'VueRouter',

  'vuex':'Vuex',

  'vue-resource': 'VueResource'

 },

 ...

}

修改src/main.js src/router/index.js 注释掉import引入的vue,vue-resource

1

2

3

// import Vue from 'vue'

// import VueResource from 'vue-resource'

// Vue.use(VueResource)

 

路由懒加载

1

2

const workCircle = r => require.ensure([], () => r(require('@/module/work-circle/Index')), 'workCircle')

const workCircleList = r => require.ensure([], () => r(require('@/module/work-circle/page/List')), 'workCircleList')

 

将一些静态js css放到其他地方(如OSS),减小服务器压力

注意这里的js文件,需要将结果抛出,然后在需要用到该js的组件中import引入

 

按需加载三方资源,如iview,建议按需引入iview中的组件

按需引用请查看iview官方文档iview

 

使用nginx开启gzip减小网络传输的流量大小

配置nginx,可以参考Nginx开启Gzip压缩大幅提高页面加载速度

 

webpack开启gzip压缩

这里需要配合Nginx服务器,Nginx开启gzip

config/index.js中

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

module.exports = {

 build: {

  ...

  // Gzip off by default as many popular static hosts such as

  // Surge or Netlify already gzip all static assets for you.

  // Before setting to `true`, make sure to:

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

  productionGzip: true, // 就是这里开启gzip,vue-cli搭建项目,这里默认为false

  productionGzipExtensions: ['js', 'css'],

 

  // Run the build command with an extra argument to

  // View the bundle analyzer report after build finishes:

  // `npm run build --report`

  // Set to `true` or `false` to always turn it on or off

  bundleAnalyzerReport: process.env.npm_config_report

 }

}

build/webpack.prod.conf.js中

使用vue-cli构建项目时,默认会有这段代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

if (config.build.productionGzip) {

 const CompressionWebpackPlugin = require('compression-webpack-plugin')

 webpackConfig.plugins.push(

  new CompressionWebpackPlugin({

   asset: '[path].gz[query]',

   algorithm: 'gzip',

   test: new RegExp(

    '\\.(' +

    config.build.productionGzipExtensions.join('|') +

    ')$'

   ),

   threshold: 10240,

   minRatio: 0.8

  })

 )

}

若首屏为登录页,可以做成多入口,登录页单独分离为一个入口

 

修改webpack配置

在原先只有一个入口叫app的基础上,再加一个叫login的入口,指向另一个入口js文件;

既然是两个页面,那么原先只有一个的HtmlWebpackPlugin也需要再添加一个,并且filename和template改成登录页的;

HtmlWebpackPlugin默认会把所有资源放进html,为了去掉不需要的资源,需要在HtmlWebpackPlugin选项里分别添加excludeChunks: ['login']和excludeChunks: ['app'];

原先的某些CommonsChunkPlugin会导致报错,删掉只剩下一个manifest的CommonsChunkPlugin就好。

 

添加登录相关文件

添加之前配好的login入口文件,与app类似,但是去掉登录页不需要的东西,如用不到的组件和样式等;

添加login入口专用的router配置文件,去掉其他路由,只留下登录页一个就好:

 

只留登录路由

添加登录页的html模板,也是去掉登录里用不到的资源。

 

修改其他细节

登录完不是用vue-router的push方法,而是改成直接修改location.href跳到另一个页面;

去除原来app路由中的login;

登录页中可以使用隐藏的iframe等方式预加载app页面中的数据(猜想)。

 

参考资料:https://www.jb51.net/article/146414.htm

Logo

前往低代码交流专区

更多推荐