前言解读
前面两篇说了针对依赖文件的优化来提升速度
这里讲一下如何从加载方式,渲染体验方面进一步提升用户体验效果
1、路由懒加载
路由懒加载,原理其实就是将原来 顶层直接import引入的方式
改为利用函数被调用时才执行的特性
结合 es11 的新特性 动态加载import(), 允许在局部作用域引用其他文件模块
{
path: '/test',
component: () => import('../views/Test.vue'),
}
或者使用 CommonJS 模块 的 require() 引入
component: () => require('../views/Test.vue')
以test路由为例,在 test 路由文件 输出日志,使用懒加载后,只有当跳转到这个路由时才会显示日志输出,否则应用一开始就将加载所有路由页面并显示日志输出
打包后也会将设置了懒加载的路由文件分离出来,生成异步 chunk 文件
当跳转到该路由页面时才会加载该文件,而不是一次性加载全部
2、体验效果优化
vue 是单页面应用,初始化完成就会将dom插入,将实例挂载到
那么可以在 vue 生成的 dom 插入之前,加入loading过渡效果,等vue插入后自动覆盖了原先的过渡效果元素,让用户视觉体验更好
在public/index.html 入口文件
<body>
<div id="app">
<div class="loading-container">
<div class="loading-spin"></div>
<span class="loading-text">努力加载中。。。</span>
</div>
</div>
</body>
引入样式
<link rel="stylesheet" href="/loading/index.css" />
.loading-container{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.loading-container .loading-spin{
border: 4px solid #f6f6f6; /* 设置边框样式 */
border-top: 4px solid #409EFF; /* 设置顶部边框样式为蓝色 */
border-radius: 50%; /* 设置边框圆角 */
width: 60px; /* 设置 loader 宽度 */
height: 60px; /* 设置 loader 高度 */
animation: spin 0.5s linear infinite; /* 添加旋转动画 */
}
.loading-container .loading-text{
margin-top: 10px;
font-size: 16px;
color: #303133;
}
@keyframes spin { /* 定义旋转动画 */
0% { transform: rotate(0deg); } /* 起始状态:不旋转 */
100% { transform: rotate(360deg); } /* 终止状态:360度旋转 */
}
这样在vue 实例挂载前就可以展示出一个加载效果,从视觉上提升体验,平滑进入应用的时间
效果
3、按需异步加载组件
Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
全局注册使用
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
局部注册使用
components: {
'my-component': () => import('./my-async-component')
}
只在需要使用的时候才会加载这个组件
4、vue-cli 去除生产环境sourceMap
source map:源映射文件,帮助开发者在浏览器的开发者工具中,将错误和日志定位到原始代码的具体位置
默认情况下,Vue CLI 会在开发环境中生成 source map 文件,以便开发者可以方便地调试代码。但是,在生产环境中,生成 source map 文件可能会暴露一些敏感信息,因此通常需要将其关闭。
要关闭 productionSourceMap
,可以在 Vue CLI 的配置文件vue.config.js
中设置 productionSourceMap: false
module.exports = {
productionSourceMap: false,
};
打包后不会生成map映射文件,大大减少打包后的体积
5、SplitChunksPlugin 拆包
在不做任何优化情况下,chunk-vendors.js
和app.js
的体积都太大了,特别是初始第三方包竟有 955kb。非常不利于首屏加载的响应速度
在 vue-cli 脚手架的vue.config.js 通过 configureWebpack 配置项覆盖掉 SplitChunksPlugin cacheGroups
项默认值的配置
将公共模块代码文件和一些依赖包拆分出来,有利于提升首屏时加载的速度
拆分代码并没有标准的方案,要结合项目的实际情况去找到最合适的拆包策略
自定义缓存组,从第三方依赖库抽离 element 、vue相关依赖 和公共代码文件
这里为测试demo项目,实际没有多少逻辑代码,所以将拆包限制改为最小,先将效果展示出来
module.exports = {
// webpack额外配置
configureWebpack: {
optimization: {
splitChunks: {
chunks: "all", // 选择哪些 chunks 进行分割,可选值有:async异步,initial同步和 all所有
minSize: 1, // 允许新拆出 chunk 的最小体积
maxSize: 0, // 旨在与 HTTP/2 和长期缓存一起使用。它增加了请求数量以实现更好的缓存。它还可以用于减小文件大小,以加快二次构建速度。
minChunks: 1, // 拆分前被 chunk 公用的最小次数
maxAsyncRequests: 5, // 每个异步加载模块最多能被拆分的数量
maxInitialRequests: 3, // 每个入口和它的同步依赖最多能被拆分的数量
enforceSizeThreshold: 0, // 强制执行拆分的体积阈值并忽略其他限制,默认50kb
cacheGroups: {
// 缓存组
vendors: {
// 第三方库
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: 10, // 缓存组权重,数字越大优先级越高
},
vueVendor: {
// vue 依赖拆包
test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/,
name: 'chunk-vue-vendors',
priority: 20, // 缓存组权重,数字越大优先级越高
},
element: {
// elementUI 单独拆包
name: "chunk-element",
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
priority: 20, // 缓存组权重,数字越大优先级越高
},
common: {
// 公共模块包
name: `chunk-common`,
minChunks: 1, // common 组的模块必须至少被 1 个 chunk 共用 (本次分割前)
priority: 0, // 缓存组权重,数字越大优先级越高
reuseExistingChunk: true, // 复用已被拆出的依赖模块,而不是继续包含在该组一起生成
},
},
},
},
}
}
打包后的效果如下