一、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); } };