优化 H5 项目的首屏加载可以提升用户体验和页面性能,以下方法是我在项目中优化的点:
1、网络
采用CDN缓存,托管到亚马逊云/阿里云存储桶,上传后记得改一下publicPath的地址
2. 资源加载
其实大部分的优化还是取决于首屏加载的资源,如果能减少首屏资源的大小,能提高加载速度
-
路由懒加载
- 懒加载简单来说就是延迟加载或按需加载,即在需要使用到路由的时候才进行加载
-
减少或者优化第三方依赖 可以通过webpack-bundle-analyzer 这个打包可视化插件看下哪些第三方依赖占用了首屏的资源加载
- lodash.js占比挺大 但项目实际就用到他的几个方法,精准引入可避免引入lodash整个依赖的引入
import { reverse, sortBy } from 'lodash' import reverse from 'lodash/reverse' import sortBy from 'lodash/sortBy'
- moment 一个处理日期时间的第三方依赖 但是体积也是有点大 如果没有一些特殊的需求 其实可以用dayjs包替代
-
webpack splitChunks 代码分割,优点如下:
-
减少初始加载时间:将代码分割成较小的块可以减少初始加载时需要下载的文件大小。这样可以加快页面的加载速度,让用户更快地看到内容。
-
提高缓存利用率:通过代码分割,可以使不经常变化的代码块与经常变化的代码块分开。这样在更新应用程序时,只需要重新加载发生变化的代码块,而缓存中的不变代码块可以继续使用,提高了缓存的利用率。
-
按需加载:通过代码分割,可以将应用程序划分为多个逻辑块,按需加载这些块。当用户进行特定操作或访问特定页面时,只需要加载与该操作或页面相关的代码块,而不是一次性加载所有代码。这样可以减少不必要的加载和提高用户体验。
-
并行加载:由于代码被分割成多个块,浏览器可以同时下载多个代码块,从而提高了加载的并行性。这可以加快整体的加载速度,特别是在具有较大代码基础的项目中。
-
代码复用:通过代码分割,可以将通用的代码块提取为共享模块,被多个入口模块使用。这样可以实现代码的复用,减少冗余代码,从而提高代码的可维护性和可扩展性。
-
动态导入支持:Webpack 的 splitChunks 功能与动态导入(Dynamic Import)结合使用时,可以实现更细粒度的代码分割。通过动态导入,可以在运行时根据需要动态加载模块,实现更灵活的代码分割策略。
下面是针对我自身项目的优化 仅供参考
-
optimization: {
nodeEnv: false,
runtimeChunk: 'single',
usedExports: true,
splitChunks: {
chunks: 'all', // 可选值:all,async 和 initial。all功能最强大,所以咱们就使用all
maxInitialRequests: Infinity, // 最大并行请求数,为了以防万一,设置无穷大即可
minSize: 500000, // 引入的模块大于200kb才做代码分割,官方默认20000,这里不用修改了
maxSize: 1000000, // 若引入的模块大于60kb,则告诉webpack尝试再进行拆分
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
},
vue: {
// 优先级
name: 'chunk-vue',
priority: 20,
test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
},
vant: {
// 优先级
name: 'chunk-vant',
priority: 20,
test: /[\\/]node_modules[\\/](vant)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
},
vuetify: {
// 优先级
name: 'chunk-vuetify',
priority: 20,
test: /[\\/]node_modules[\\/](vuetify)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
},
lodash: {
// 优先级
name: 'chunk-lodash',
priority: 20,
test: /[\\/]node_modules[\\/](lodash)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
},
'vue-easyrefresh': {
// 优先级
name: 'chunk-vue-easyrefresh',
priority: 20,
test: /[\\/]node_modules[\\/](vue-easyrefresh)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
},
'moment-timezone': {
// 优先级
name: 'chunk-moment',
priority: 20,
test: /[\\/]node_modules[\\/](vuetify)[\\/]/,
chunks: 'all',
reuseExistingChunk: true
}
}
}
}
-
开启gizp压缩
- vue.config.js
onst CompressionWebpackPlugin = require("compression-webpack-plugin");
configureWebpack: {
plugins:
[
new CompressionWebpackPlugin({
algorithm (input, compressionOptions, callback) {
return zopfli.gzip(input, compressionOptions, callback)
},
compressionOptions: {
numiterations: 15,
},
minRatio: 0.99,
test: productionGzipExtensions,
}),
new CleanWebpackPlugin(),
]
}
- 另外需要配置下Nginx
#开启和关闭gzip模式
gzip on;
#gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 6;
# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;
# nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;
- 关闭预请求 Prefetch、Preload
Vue-Cli3默认会使用preload-webpack-plugin对chunk资源做preload、prefetch处理,入口文件preload,路由chunk则是prefetch。
chainWebpack: config => {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
}
3. 视觉优化 利用等待动画过场
- 骨架屏
- loading动画