一、webpack层面优化
CDN加载方式替换import方式
原理:
浏览器从服务器上下载 CSS、js 和图片等文件时都要和服务器连接,而大部分服务器的带宽有限,如果超过限制,网页就半天反应不过来。而 CDN 可以通过不同的域名来加载文件,从而使下载文件的并发连接数大大增加,且CDN 具有更好的可用性,更低的网络延迟和丢包率 。
操作:
// 文件:./src/index.html
<script src="https://cdn.bootcss.com/vue/2.5.3/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.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/clipboard.js/2.0.4/clipboard.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
图片base64转码
目的:图片转base64后,图片打包进dist/app.js中,随js一起加载,减少http请求次数。图片转成base64后,文件体积变大了大约1/3左右
注意:
- 文件的base64编码存储到了js文件中
- vue-webpack模板的默认设置限制了转码的文件大小为10000B以下
- 静态文件目录中的所有文件不会被转码,也就是/static下的所有文件都不会被转码
- 如果所有图片均转码为base64,那么很容易造成存储base64的js文件过大,一方面会造成资源加载时间过长的白屏问题,另一方面也会给js解释器带来非常大的负担,这样反而起不到优化的作用,而且会非常影响体验
- 如果你非要让所有图片转为base64,可以修改webpack中的url-loader配置
js/css文件压缩
1.js文件切割
2.js文件压缩
3.css文件切割加载
4.css文件压缩
图片压缩
公共部分抽离
1.公共js文件抽离
2.公共css文件抽离
文件:./src/app.vue
<style lang="less">
@import '~@/assets/styles/common.less';
</style>
3.less公共变量全局设置
方案一:全局配置
文件: build/utils.js
// cssLoaders中新增lessResourceLoader函数
// 修改return中less: generateLoaders('less')改为less: lessResourceLoader()
// 将全局less文件引入resources参数中
exports.cssLoaders = function (options) {
function lessResourceLoader(){
var loaders = [
cssLoader,
'less-loader',
{
loader: 'sass-resources-loader',
options: {
resources: [
// 引入全局less文件
path.resolve(__dirname, '../src/assets/styles/variables.less')
]
}
}
];
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
return {
// less: generateLoaders('less'),
less: lessResourceLoader()
}
}
方案二:在每个vue文件style标签中import引入
import '~@/assets/styles/variables.less'
externals配置不被打包的js文件
文件: ./build/webpack.base.config.js
externals:{
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex':'Vuex',
'clipboard':'Clipboard',
'axios':'axios',
'vueLazyload':'LazyContainer'
},
键值对中的值为三方件源码中抛出的全局变量
设置是否生成source文件
文件:./build/webpack.prod.config.js
二、业务代码层面优化
事件销毁
created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
图片懒加载
原理:图片过多,优先加载可视区域内的图片
方案一:插件
// 安装vue-lazyload插件
npm install vue-lazyload --save-dev
// main.js中引入并全局注册
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.3,
loading: require('@/assets/p/90_90.png'),
attempt: 3,
try: 2 //加载图片数量
})
preLoad:1.3, //类型Number,默认1.3.表示lazyload的元素距离页面底部距离的百分比.计算值为(preload - 1).
attempt:3, //图片加载失败后的重试次数.默认为3.
error:'', //类型string.图片加载失败后的显示的失败图片路径.
loading:'', //类型string.图片正在加载中显示的loading图片的路径.
listenEvents:[], //类型array.默认['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove'].即是在监听上述事件中,判断图片是否在preload的位置.如果你不想在那么多事件中判断,可以指定一个或者几个.例如如果你给这个属性只指定['touchmove'].那么scroll 屏幕不会加载图片,只有手指滑动屏幕才会加载图片.
adapter:'', //注册img的loading,loaded,error三个状态的回调函数,参数会暴露懒加载的img元素,可以对其进行操作.
filter:'', // img未加载之前,解析到src 的时候注册的回调函数.可以在加载图片之前,对src进行修改.注册在filter下的所有的函数都会执行
lazyComponent:false,//类型Boolean.是否启用懒加载组件.组件中的内容只有在出现在preload的位置中才会加载组件.这个lazyloadComponent 组件有个缺点就是,组件在加载前是什么都不渲染的,这样子的话,有可能会影响布局,以及加载前到加载后的切换不好,有点突兀和生硬.挖坑(vue懒加载组件)
observer:false, //是否启用IntersectionObserver,这个api有兼容问题
observerOptions:{} //默认{ rootMargin: '0px', threshold: 0.1 }主要是我对这个pai不熟,按照vue-lazyload的说法是开启之后,对很多节点的情况会优化性能.挖坑吧
// 在img标签中用v-lazy代替src
<img v-lazy="hotPurchaseImgList[index].imgUrl">
本地模拟
// 数据返回前渲染空页面
// 数据返回后,渲染正常页面
<listX @isShowListX="getIsShowListX" v-if="isShowListX"/>
<listXP v-else="isShowListXP"/>
路由懒加载
const classify =
{
path: '/classify',
name: 'classify',
meta: { title: '分类' },
redirect: '/classify/index',
component: () => import('@/components/router'),
children: [{
path: 'index',
name: 'classifyIndex',
meta: { title: '分类' },
component: () => import('@/view/classify/index')
}, {
path: 'list',
name: 'classifyList',
meta: { title: '分类' },
component: () => import('@/view/classify/classListForItem')
}]
}
export default classify
三方件按需加载
方案一:babel-plugin-import按需引入 (以mand-mobile为例)
// 安装babel-plugin-import插件
npm install babel-plugin-import -D
// 修改.babelrc文件
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
方案二:babel-plugin-component按需引入 (以element-ui为例)
// 安装babel-plugin-component插件
npm install babel-plugin-component -D
// 修改.babelrc文件
{
"plugins": [
["component", {
"libraryName": "element-ui",
"libraryDirectory": "lib",
"styleLibraryName": "theme-chalk"
}]
]
}
// main.js中按需引入
import Vue from 'vue';
import { Button, Select } from 'element-ui';
Vue.use(Button)
Vue.use(Select)
显示类数据冻结双向绑定,减少组件初始化时间
原理: Vue双向绑定采用Object.defineProperty进行数据劫持实现,针对显示类数据,无需进行数据劫持,采用Object.freeze冻结对象
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};