SPA单页面应用优化VUE性能优化

来源:程序思维浏览:2786次
Spa单页面应用比如vue、react、angular都是属于单页面应用,那么如何优化呢?咱们拿vue举例。

SPA单页面应用优化VUE性能优化

单页面应用离不开构建工具比如webpack、fis3、gulp等,目前应用最多的就是webpack,咱们就用webpack来做优化,webpack能做哪些优化呢?

一、 CSS和JS压缩合并

由于webpack本身集成了UglifyJS插件(webpack.optimize.UglifyJsPlugin)来完成对JS与CSS的压缩混淆,无需引用额外的插件,
其命令 webpack -p 即表示调用UglifyJS来压缩代码,还有不少webpack插件如 html-webpack-plugin 也会默认使用UglifyJS。

uglify-js的发行版本只支持ES5,如果你要压缩ES6+代码请使用开发分支。

UglifyJS可用的选项有:
  • parse 解释
  • compress 压缩
  • mangle 混淆
  • beautify 美化
  • minify 最小化//在插件HtmlWebpackPlugin中使用
  • CLI 命令行工具
  • sourcemap 编译后代码对源码的映射,用于网页调试
  • AST 抽象语法树
  • name 名字,包括变量名、函数名、属性名
  • toplevel 顶层作用域
  • unreachable 不可达代码
  • option 选项
  • STDIN 标准输入,指在命令行中直接输入
  • STDOUT 标准输出
  • STDERR 标准错误输出
  • side effects函数副作用,即函数除了返回外还产生别的作用,比如改了全局变量
列一份配置:

//使用插件html-webpack-plugin打包合并html
//使用插件extract-text-webpack-plugin打包独立的css
//使用UglifyJsPlugin压缩代码
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require("webpack");
module.exports = {
  entry: {
    bundle : './src/js/main.js'
  },
  output: {
    filename: "[name]-[hash].js",
    path: dirname + '/dist'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use: 'url-loader?limit=8192'
      }
    ]
  },
  resolve:{
      extensions:['.js','.css','.json'] //用于配置程序可以自行补全哪些文件后缀
  },
  plugins:[
    new HtmlWebpackPlugin({
      title: 'hello webpack',
      template:'src/component/index.html',
      inject:'body',
      minify:{ //压缩HTML文件
         removeComments:true,  //移除HTML中的注释
         collapseWhitespace:true  //删除空白符与换行符
       }
    }),
    new ExtractTextPlugin("[name].[hash].css"),
    new webpack.optimize.UglifyJsPlugin({
      compress: {   //压缩代码
        dead_code: true,  //移除没被引用的代码
        warnings: false,   //当删除没有用处的代码时,显示警告
        loops: true //当do、while 、 for循环的判断条件可以确定是,对其进行优化
      },
      except: ['$super', '$', 'exports', 'require']  //混淆,并排除关键字
    })
  ]
};

这里需要注意的是压缩的时候需要排除一些关键字,不能混淆,比如$或者require,如果混淆的话就会影响到代码的正常运行。

列几个压缩时常有的属性:

1. dead_code -- 移除没被引用的代码
2. loops -- 当 do 、 while 、 for 循环的判断条件可以确定是,对其进行优化。
3. warnings -- 当删除没有用处的代码时,显示警告

二、 代码分割按需加载(require.ensure)

require.ensure()
webpack 在编译时,会静态地解析代码中的 require.ensure(),同时将模块添加到一个分开的 chunk 当中。这个新的 chunk 会被 webpack 通过 jsonp 来按需加载。

语法如下:

require.ensure(dependencies: String[], callback: function(require), chunkName: String)
依赖 dependencies
这是一个字符串数组,通过这个参数,在所有的回调函数的代码被执行前,我们可以将所有需要用到的模块进行声明。

回调 callback
当所有的依赖都加载完成后,webpack会执行这个回调函数。require 对象的一个实现会作为一个参数传递给这个回调函数。因此,我们可以进一步 require() 依赖和其它模块提供下一步的执行。

chunk名称 chunkName
chunkName 是提供给这个特定的 require.ensure() 的 chunk 的名称。通过提供 require.ensure() 不同执行点相同的名称,我们可以保证所有的依赖都会一起放进相同的 文件束(bundle)。

让我们来看以下的项目

\\ file structure
    |
    js --|
    |    |-- entry.js
    |    |-- a.js
    |    |-- b.js
    webpack.config.js
    |
    dist
\\ entry.js

require('a');
require.ensure([], function(require){
    require('b');
});

\\ a.js
console.log('***** I AM a *****');

\\ b.js
console.log('***** I AM b *****');
\\ webpack.config.js
var path = require('path');

module.exports = function(env) {
    return {
        entry: './js/entry.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    }
}
通过执行这个项目的 webpack 构建,我们发现 webpack 创建了2个新的文件束, bundle.js 和 0.bundle.js。

entry.js 和 a.js 被打包进 bundle.js.

b.js 被打包进 0.bundle.js.

require.ensure 内部依赖于 Promises。 如果你在旧的浏览器中使用 require.ensure 请记得 去 shim Promise. es6-promise polyfill.

require.ensure() 的坑点
空数组作为参数
require.ensure([], function(require){
    require('./a.js');
});
以上代码保证了拆分点被创建,而且 a.js 被 webpack 分开打包。

依赖作为参数
require.ensure(['./a.js'], function(require) {
    require('./b.js');
});
上面代码, a.js 和 b.js 都被打包到一起,而且从主文件束中拆分出来。但只有 b.js 的内容被执行。a.js 的内容仅仅是可被使用,但并没有被输出。

想去执行 a.js,我们需要异步地引用它,如 require('./a.js'),让它的 JavaScritp 被执行。

那么require.ensure如何在vue中使用呢?
require.ensure主要是在vue的路由中使用,如果不使用代码分割随着页面的增多build之后app.727c5a981063de8a5ac8.js会越来越大。使用之后会将这个js文件按页面数量分割从而做到页面按需加载js。废话少说看代码:
在router/index.js里面:
比如首页路由:
const INDEX = r => require.ensure([], () => r(require('../components/home/index/index')), 'index')
export default [
  {
    path: '/',
    component: INDEX,
    meta: { title: '首页'}
  }
]

好啦,vue中的代码分割就是这么使用简单吧!

然后咱们在看代码中如何优化?

一、图片懒加载

为什么要使用图片懒加载?

首先我们来了解一下懒加载是为了解决什么问题。当我们在项目中遇到一些比较大的场景,里面包含着数以百计的图片,当用户访问这些页面的时候,用户等待的时间特别长,这样的话,就有可能导致一部分的用户没有耐心,而丢失这部分用户,于是就有了这里的图片懒加载。在用户刚进入场景的时候,先加载几页的图片,开始显示给用户,然后在用户每翻一页时,再相应的加载后面对应的一页中的图片,这样,如果用户看了几页不想看了,后边的图片就不用加载了,减轻了服务器的压力。而相应的,用户在进入场景时,等待的时间也减少了许多。

懒加载在一些大型的网站中见到的比较多,因为网站考虑到性能、流量及用户体验方面的问题,在用户点击开网站的首页的时候,网站想尽可能的显示更多的信息给用户,又要考虑到服务器的性能的问题,还不能让用户等待的时间过长,所以这里就会使用图片的懒加载。图片的懒加载可以让用户按照需求从服务器上加载图片,这样即节省了用户在代开首页时的等待时间,也节省了服务器的流量,所以是一个好的选择。

使用vue-lazyload做图片懒加载减少请求数。

1. 安装插件:

npm install vue-lazyload --save-dev

2. main.js引入插件:

import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad,{
    error:'./static/error.png',
    loading:'./static/loading.png'
})

3. vue文件中将需要懒加载的图片绑定 v-bind:src 修改为 v-lazy
<img class="item-pic" v-lazy="newItem.picUrl"/>

二、针对第三方库文件使用cdn方式

之前我是使用npm安装之后import方式,这样就相当于一起打包到了vendor文件里了。

按照bootstrap官网引入相应的cdn文件后(包括jquery和bootstrap),我的项目最大文件大小变成了680kb,加载速度从8.5s变成了5.8s。

然后试图引入element-ui之后,最大文件大小没多大变化,但是加载速度从5.8s变成了4.2s。

接着又引入了vue和element-ui cdn文件,这下网站有了巨大突破,最大文件竟然降到了37kb,自己都被惊讶到了,加载速度也从4.2s变成了80ms,整个网站加载完成只花了1.5s,终于达到了秒开的效果。

如何使用cdn方式呢?

1、 提取js/css到cdn

以一个vue项目为例。项目引用了vue、axios、iview、iview的css:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import iView from 'iview'
import 'iview/dist/styles/iview.css'

2、 提取js到外部,减小vendor.js体积

1. 在/build/webpack.base.conf.js中,增加externals:
module.exports = {
    externals: {
        'vue': 'Vue',
        'axios': 'axios',
        'iview': 'iview'
    }
}
注意,externals的键值对中,键应为在/src/main.js中import的名称,值为引用的外部文件export的名称。以cdn.bootcss.com的库文件为例,vue的导出名为Vue,mint-ui为MINT,vue-router为VueRouter。

3、复制/index.html为/index.dev.html,并修改/build/webpack.dev.conf如下:

plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      // template: 'index.html',
      template: 'index.dev.html',
      inject: true
    })
]
* 这是为了解决dev环境下,重复引用库的问题。

4、在/index.html中,引入cdn文件

<body>
    <div id="app"></div>
    <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
    <script src="https://cdn.bootcss.com/iview/2.6.0/iview.min.js"></script>
</body>
可见,处理前vender.js大小148KB,处理后大小13.7KB。
另增加3个CDN文件,大小34.9KB、5.6KB、115KB,增加115.5KB。
总体积变化不大。将大体积文件放置在cdn上,减小了服务器流量压力,加快了不同地区网页加载速度。

5、提取css到外部,减小app.css体积

在/src/main.js中,前端框架的CSS引用,都可去除,并改为在/index.html中引用其CDN版本。
1. 去除/src/main.js中的CSS文件import,改为在开发环境下require
// import 'iview/dist/styles/iview.css
if (process.env.NODE_ENV === 'development') {
  require('mint-ui/lib/style.css')
}

6、在/index.html中,引入cdn文件

<head>
    <link href="https://cdn.bootcss.com/iview/2.6.0/styles/iview.css" rel="stylesheet">
    <title>app</title>
</head>

三、使用第三方框架和插件按需加载

对于项目中用到的一些UI框架,比如 Element UI 、Mint UI、Cube-UI 等等。如果我们只使用框架的部分组件,那么可以不要引入整个框架,按需引入用到的组件。
以Mint UI为例:

// 引入全部组件 
import Mint from 'mint-ui'; 
import 'mint-ui/lib/style.css' 
Vue.use(Mint);

// 按需引入部分组件 
import { CellSwipe } from 'mint-ui'; 
Vue.component(CellSwipe.name, CellSwipe);

好了spa单页面应用的优化就写到这里,希望对大家有帮助。
精品好课
React实战视频教程仿京东移动端电商
React是前端最火的框架之一,就业薪资很高,本课程教您如何快速学会React并应用到实战,对正在工作当中或打算学习React高薪就业的你来说,那么这门课程便是你手中的葵花宝典。
HTML5视频播放器video开发教程
适用人群1、有html基础2、有css基础3、有javascript基础课程概述手把手教你如何开发属于自己的HTML5视频播放器,利用mp4转成m3u8格式的视频,并在移动端和PC端进行播放支持m3u8直播格式,兼容...
jQuery视频教程从入门到精通
jquery视频教程从入门到精通,课程主要包含:jquery选择器、jquery事件、jquery文档操作、动画、Ajax、jquery插件的制作、jquery下拉无限加载插件的制作等等......
最新完整React+VUE视频教程从入门到精,企业级实战项目
React和VUE是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React和VUE并应用到实战,教你如何解决内存泄漏,常用库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习Re...
最新完整React视频教程从入门到精通纯干货纯实战
React是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习React高薪就...
Vue2+Vue3+ES6+TS+Uni-app开发微信小程序从入门到实战视频教程
2021年最新Vue2+Vue3+ES6+TypeScript和uni-app开发微信小程序从入门到实战视频教程,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己...
HTML5基础入门视频教程易学必会
HTML5基础入门视频教程,教学思路清晰,简单易学必会。适合人群:创业者,只要会打字,对互联网编程感兴趣都可以学。课程概述:该课程主要讲解HTML(学习HTML5的必备基础语言)、CSS3、Javascript(学习...
VUE2+VUE3视频教程从入门到精通(全网最全的Vue课程)
VUE是目前最火的前端框架之一,就业薪资很高,本课程教您如何快速学会VUE+ES6并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习VUE高薪就...
收藏
扫一扫关注我们