1.打包配置层面
vue打包优化/webpack打包优化
1.1使用report分析包中较大的bundle
1.2打包分离 external
一些较大的依赖或插件,利用内网资源或cdn的缓存策略,优化加载时长
external:{
'element-ui':ELEMENT
moment:'moment'
echarts:'echarts'
}
对于key、value的说明:
++key是包名
import Vue from 'vue',‘vue’就是包名
++value是script引入之后,在window对象上添加的属性
通过script引入vue,会在window对象上添加一个Vue的属性
**body--id='app'下面直接引入对应的script文件,在head中引入elementui样式文件
**需要注意的是,要注意分离打包的度。分离的目的主要是俩:
**a.利用浏览器的请求并发,同时请求几个分开的包,而不是一次请求两个超大的js包。
**b.利用浏览器的缓存机制,将一些不会更改的js包缓存下来,避免每次都去请求最新的包
**但是如果分离的粒度较小,会导致在首页加载资源的请求变多,会造成首页加载延迟
整体配置方面,可以看这篇文章 blog.csdn.net/xzwwjl1314/…
1.3drop_console
生产环境中去掉console信息,避免不必要的内存泄漏的情况
configureWebpack: (config) => {
if (process.env.NODE_ENV === "production") {
config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true;
config.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = true;
}
},
1.4开启资源gzip
使用CompressionWebpackPlugin压缩文件形成压缩包,同时服务器要配置允许使用gzip资源,这样就可以做到让浏览器请求加载gzip资源,并在本地解析
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg|eot|ttf|woff)(\?.*)?$/i;
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
const plugins = [];
plugins.push(
new CompressionWebpackPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
}
}
用到的属性:
test:正则表达式,可以用来控制哪些后缀的文件需要打包
filename:gzip文件的名称[path].gz[query]
threshold:10240 大于10k
algorithm:'gzip'压缩方式
minRatio: 还是不知道啥意思
1.5配置资源缓存节省带宽
协商缓存 强缓存(也叫本地缓存,直接缓存到本地不与服务器通信)返回200(from cache)
强缓存 优先于 协商缓存
强: expries--绝对时间
cache-control
max-age:数值,单位秒
no-cache 不使用本地缓存,使用协商缓存
no-store 不使用缓存,直接从服务器请求最新资源
public 被代理服务器与浏览器同时缓存
private 仅被浏览器缓存
协商:etag-->if-none-match 返回304(Not Modified)
last-modified-->if-modified-since
etag判断文件内容是否修改
last-modified判断上次修改时间
etag的优点:
1.文件周期性改变,只是文件信息改变,但是内容不变
2.文件改变的特别频繁,1s改n次,last-modified最小精确到秒
3.某些服务器不能精准的得到文见最后修改的时间
etag的优先级>last-modified
1.6使用按需加载模块
element-ui
按需加载第三方插件,elementUI(需要另外安装babel-plugins-component)
babel.config.js:
plugins:[
[
'component',
{
'libraryName':'element-ui',
'styleLibraryName':'theme-chalk'
}
]
]
import {Button} from "element-ui";
Vue.use(Button)
echarts
引入主模块
let echarts =require('echarts/lib/echarts');
引入折线柱状图等组件
require('echarts/lib/chart/line')
require('echarts/lib/chart/bar')
引入提示框,title,图例
...
Vue.prototype.$echarts=echarts
1.7 路由、组件动态加载
动态路由:
routes:[
{
component:()=>import("@/views/normal")
}
]
//提供一个封装路由懒加载的函数
routes.js:
function load(component) {
return ()=>import(/* webpackChunkName: "[request]" */`@/views/${component}`)
}
const compA = 'comp/compA'
{
path: '/case',
name: 'case',
component:load(compA)
}
//这里不仅是路由懒加载,还用到webpack魔法注释,能够将当前组件单独打包到js中,分离打包
动态组件:
<transition name='fade'>
//动态赋值componentId控制内部加载的组件,结合componentShow控制组件的展示与否,这样就避免在页面一开 始就加载了所有的组件
<component v-if='componentShow' :is="componentId" />
</transition>
//js逻辑通过逻辑判断,动态的赋给componentId,避免在一开始加载所有可能的组件然后再一一逻辑判断
componentId= () => import(`@/components/AreaLaw/Other/index`);
1.8生产环境移除preload与prefetch
去除首页预加载其他页面的css与js,优化首页加载速度 config.plugins.delete('preload')
config.plugins.delete('prefetch')
preload提升资源加载优先级,通过 只是预加载了资源,但是资源加载完成后并不会执行,所以需要在想要执行的地方通过
但是也有一个例外,因为 CSS 的加载也是通过 标签引入的,所以可以在加载之后,onload事件中,修改rel属性
当 onload 事件触发的时候修改 rel 属性的值,使得它由原来的预加载样式变成引入样式
如果通过 preload 加载了资源,但是又没有使用它,则浏览器会报一个警告
preload与prefetch在加载时候的区别 preload会使资源优先加载,比如:此时,b.js会被优先加载
prefetch则是在浏览器都加载完了相关的js css,也解析完毕了html文件,页面load结束之后,才加载prefetch的相关文件。
preload会下载并解析文件。但prefetch只会下载文件不会解析。 preload是当前页面必须用到的文件。但prefetch大部分不是当前页面需要的,仅仅是之后的页面需要用的资源
但是: 这里有问题
***如果prefetch的文件特别多的话,会阻碍接口的调用的,比如prefetch 10多个文件之后,在调用了页面的接口,这样就会使得页面加载的更慢了。
vue默认是打开preload与prefetch的,所以要关闭这俩,让首页展示的更快些
***再就是如果网速比较慢,但现在确提前prefetch了很多文件,会使页面加载的更缓慢
1.9打包时候分离代码,提取公共代码
splitChunk --结合缓存 blog.csdn.net/ZYS10000/ar…
vue项目直接运行build-report即可
代码分离a:目的:利用浏览器并发加载,减少某个模块的大小,达到减少加载时间的目的
1.9.1 分离方法1:动态加载 import()。动态路由、动态组件。
其中动态路由的rouer可以使用webpack魔法注释
function load(component){
return ()=>import(/* webpackChunkName: "[request]" */ /* webpackPrefetch: true */`@/views/${component}`
)
}
//webpackChunkName: "[request]是解析之后js文件名称
//webpackPrefetch: true */ 设置组件预加载。在浏览器空闲的时候加载路由,不会阻碍页面load。
//不过动态路由本身就应该用到的时候去加载,所以可以不去配置。
1.9.2分离方法2:通过splitChunks
1.9.2.1 chunks:三个参数
all(动态引入静态进入都会分离打包,并只会生成一个相关bundle文件)
async(只打包动态加载的模块)
initial(只打包静态引入的资,并且生成了多个bundle文件)
1.9.2.2 cacheGroups:
单独分离某个模块
vendors: {
name: `app-chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,//优先级
chunks: 'all'
},
echarts: {
chunks: 'all',
name: `echarts`,
test: /echarts|zrender/,
priority: 10,
}
echarts的priority需要大于vendors的,否则不能分离出来
//完整的一个配置:
chainWebpack: (config) => {
if (process.env.NODE_ENV === "production") {
config.optimization.minimize(true);
}
config.plugins.delete("prefetch");
config.plugins.delete("preload");
config.optimization.splitChunks({
chunks: "initial",
cacheGroups: {
vendors: {
name: `app-chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'all'
},
echarts: {
chunks: 'all',
name: `echarts`,
test: /echarts|zrender/,
priority: 10,
},
// default: {
// //如果有一个文件被用了两次,会被打包成一个单独的文件
// minChunks: 2,
// filename: "common_[id].js",
// //优先级 一般是负数
// priority: -10,
// },
}
// cacheGroups: {
// vendors: false,
// common: false
// }
});
},
**关于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
})
}
}
2.代码层面
2.1 接口请求层面
合并请求,防止页面请求过多的请求
2.2 使用虚拟列表优化无限滚动的长列表
2.3 使用文档碎片document.createDocumentFragment()
2.4 for循环一定要加上key值,减少diff算法时间
2.5 关于回流重绘
减少回流重回的次数 通过style.cssTest+=统一修改
切换类名统一修改样式
浏览器会将多次的回流放在一个队列中,但是如果获取dom元素的布局信息,就会强制清空队列进行回流。所以可以缓存dom布局信息
2.6 防止浏览器内存泄漏
2.6.1 给滚动事件、输入seggest事件等频繁触发的事件添加节流、防抖
2.6.2 生产环境一定要去掉console.log,打印信息过大也会造成内存泄漏
2.6.3 第三方插件使用完成后,一定要销毁实例(echarts--despose),避免游离的dom节点
2.6.4 event-bus监听函数,在destoryed生命周期要关闭(on---$off)
2.6.5 localstorage中不要存放过大的数据量,优化性能
2.6.6 在页面destory的时候,也要移除window上的全局事件
2.6.7 读取了dom元素的信息存入到了变量中,在使用完成后,要将变量置为null,避免游离的dom节点
2.7 图片懒加载、列表的无限滚动
都会用到交叉管理器 intersectionObserver 列表的无限滚动要注意padding-top padding-bottom进行元素占位,否则滚动的时候会出现抖动问题 vue框架对性能优化所做的配置操作