注册
web

H5性能优化-打开效率提升了62%

一、达成的结果


app嵌套h5 加载效率提升了62%。时间从平均2.259s 降到了0.852s


二、优化过程


思路:优化原生webview+h5 ,先测试webview点击到创建时间 120ms(无需优化)。webview 提供了 api 测试 加载url 的进度。但是没提供具体的类似pc端网络的工具。所以就通过ai搜索一些工具。发现阿里云的arms 方便引入。


测试设备 android荣耀50、华为meta9、华为p40、oppo


开发环境测试


测试样本:优化前后各测试10次。


测试移动端h5 引入了阿里云的arms arms.console.aliyun.com/ 可以查看加载某个url的时候 请求的js css、图片、网络请求 跟网页版的网络类似。


import ArmsRum from '@arms/rum-browser'

ArmsRum.init({
pid: 'ha63j3v892@efe71d242023cd5',
endpoint: 'https://ha63j3v892-default-cn.rum.aliyuncs.com',
// 设置环境信息,参考值:'prod' | 'gray' | 'pre' | 'daily' | 'local'
env: 'prod',
// 设置路由模式, 参考值:'history' | 'hash'
spaMode: 'hash',
collectors: {
// 页面性能指标监听开关,默认开启
perf: true,
// WebVitals指标监听开关,默认开启
webVitals: true,
// Ajax监听开关,默认开启
api: true,
// 静态资源开关,默认开启
staticResource: true,
// JS错误监听开关,默认开启
jsError: true,
// 控制台错误监听开关,默认开启
consoleError: true,
// 用户行为监听开关,默认开启
action: true,
},
// 链路追踪配置开关,默认关闭
tracing: false,
})

export default ArmsRum

步骤一、懒加载echarts


以前的代码


import Api from '@/api'
import * as echarts from 'echarts'
import dayjs from 'dayjs'
export default {
}

现在的代码


async getRepairChart() {
const echarts = await import('echarts')
// xxx
const chartDom = document.getElementById('repairChart')
const myChart = echarts.init(chartDom)
const option = {
}
myChart.setOption(option)
},

通过F12查看网络 发现加载列表的时候有出现echartsxxx.js 而且有800多k ,所以就考虑加载列表不应该去加载数据看板的数据。


优化前,测试前日志打印



均是3.234s 然后 当然还测试了华为p40 、oppo机器 由于系统不一样时间有些差别


测试后日志打印



平均是1.71s




华为meta9 9年前的老手机打印log



平均也2s多


优化后



不到0.8s


步骤二、禁用预加载、路由懒加载


通过查看网络发现请求dev-haolipei.cias.cn/app/#/takeO… 超级多的js 跟css


一张图都截取不完。当时就感觉肯定请求了很多无关紧要的资源。



npm run build 执行后查看dist目录index.html 的确很触目惊心 加载了太多没必要的资源了。



module.exports = {
publicPath,
devServer: {
disableHostCheck: true,
// host: 'localhost.cias.cn',
proxy: {
'/api': {
target,
changeOrigin: true,
// cookieDomainRewrite在手机调试时用得上
// cookieDomainRewrite: '',
pathRewrite: {
'^/api': '',
},
},
'/media': {
target,
changeOrigin: true,
pathRewrite: {
'^/media': '',
},
},
},
},
chainWebpack: config => {
// 禁用预加载
config.plugins.delete('preload')
config.plugins.delete('prefetch')
},
}

禁用它们的核心好处

1. 减少不必要的网络请求,节省带宽


  • preload 可能会强制加载一些 “非关键资源”(如配置不当的情况下,预加载了体积大但当前页面暂时用不到的资源),导致带宽浪费。
  • prefetch 会预加载未来可能访问的路由 chunk(如用户可能不会点击的低频页面),如果用户最终没有访问这些页面,预加载的资源就成了 “无效请求”,尤其对移动端用户(流量有限)不友好。

禁用后,资源仅在明确需要时才会加载(如用户进入对应路由时),避免 “提前加载但用不上” 的浪费。


2. 避免阻塞关键资源加载,提升首屏速度


  • 浏览器对同一域名的并发请求数有限制(HTTP/1.1 通常为 6 个)。preload 加载的资源会占用并发名额,可能阻塞当前页面真正需要的关键资源(如核心 JS/CSS),导致首屏渲染延迟。
  • 例如:若 preload 预加载了一个 2MB 的非关键 chunk,可能会挤占首屏 JS 的加载带宽,导致页面 “白屏时间” 变长。

禁用后,浏览器的并发资源会优先分配给当前页面的核心资源,减少阻塞。


3. 避免缓存资源被 “无效资源” 占用

浏览器缓存空间有限,prefetch 预加载的大量 “未来可能用到” 的 chunk 会占用缓存空间,可能导致真正需要长期缓存的核心资源(如 chunk-vendors.js)被挤出缓存,下次访问时需要重新加载。


禁用后,缓存可优先保留关键资源,提升二次访问速度。


4. 适配低网速 / 弱网环境

在 3G、偏远地区等弱网环境下,preload/prefetch 的预加载行为会加剧网络拥堵:



  • 预加载的资源可能耗时过长,导致当前页面的核心资源加载超时。
  • 禁用后,资源加载更 “轻量化”,优先保证当前页面可用,符合弱网环境的用户体验需求。

5. 减少开发环境的冗余加载

在开发环境中,Webpack 会频繁编译资源,preload/prefetch 可能导致每次热更新时加载大量无关资源,拖慢开发服务器响应速度,影响开发体验。禁用后可简化开发环境的资源加载逻辑,提升热更新效率。


注意:并非所有场景都适合禁用

preload/prefetch 本身是性能优化手段,若项目存在以下情况,可能需要保留或部分配置:



  • 首屏依赖的关键资源(如核心 CSS、字体)体积大,preload 可加速其加载。
  • 高频访问的路由(如首页→列表页),prefetch 可提前加载列表页 chunk,提升跳转速度。

因此,禁用的合理性取决于项目场景:资源体积大、用户网络不稳定、低频路由多的项目(如移动端 H5)更适合禁用;高频路由明确、网络环境好的项目可选择性保留


路由懒加载

必须写上 /* webpackChunkName: "system-setting" */


以前的代码


	{
path: '/takeOrder',
name: 'HomeTakeOrder',
component: () =>
import(
'@/views/baosi/orderList.vue'
),
meta: {
title: '推返修列表',
keepAlive: true,
},
}

懒加载路由模式


const HomeTakeOrder = () =>
import(/* webpackChunkName: "take-order" */ '@/views/baosi/orderList.vue')

{
path: '/takeOrder',
name: 'HomeTakeOrder',
component: HomeTakeOrder,
meta: {
title: '推返修列表',
keepAlive: true,
},
},

这样的好处 打包后 会有路由名称



对比



继续测试打印log



可以看看网络请求 就只有5个js文件 总体积不到300k



平均是0.852,基本达成要求


通过npm run build 本地打包看看文件对比大小。


1、体积巨减!!!


2、加载的文件名称是路由名称+hash值


优化前



优化后



三、内部项目具体实践


(增值移动端h5项目可以参考以下操作)


1、禁用预加载


module.exports = {
publicPath,
devServer: {
disableHostCheck: true,
// host: 'localhost.cias.cn',
proxy: {
'/api': {
target,
changeOrigin: true,
// cookieDomainRewrite在手机调试时用得上
// cookieDomainRewrite: '',
pathRewrite: {
'^/api': '',
},
},
'/media': {
target,
changeOrigin: true,
pathRewrite: {
'^/media': '',
},
},
},
},
chainWebpack: config => {
// 禁用预加载
config.plugins.delete('preload')
config.plugins.delete('prefetch')
},
}

2、将路由全部改成懒加载


并且路由需要/* webpackChunkName:"take-order" */


	{
path: '/takeOrder',
name: 'HomeTakeOrder',
component: () =>
import(
/* webpackChunkName:"take-order" */ '@/views/baosi/orderList.vue'
),
meta: {
title: '推返修列表',
keepAlive: true,
},
}

3、组件懒加载


以前常见写法 就是一进来 把所有组件的都加载进来


比如这个车牌号组件有120k 对于比较大一点的组件可以用懒加载 。


	<van-popup v-model="showPlatePopup" position="bottom" :overlay="false">
<keyboard
v-model="baseInfo.plateNumber"
:show.sync="showPlatePopup"
@input="handlePlateInput"
></keyboard>


import Keyboard from '@/components/numberplate/vnp-keyboard.vue'

export default {
name: 'CreateOrder',
components: {
MultiSelectPopup,
DispatchingPopup,
DispatchFailPopup,
DispatchFinishPopup,
Keyboard,
},

}

懒加载代码


用这个方式可以直接在网络中查看到对应组件的名称和大小


<van-popup
v-if="showPlatePopup"
v-model="showPlatePopup"
position="bottom"
:overlay="false"
>
<keyboard
v-model="baseInfo.plateNumber"
:show.sync="showPlatePopup"
@input="handlePlateInput"
></keyboard>
</van-popup>

export default {
name: 'CreateOrder',
components: {
MultiSelectPopup,
DispatchingPopup,
DispatchFailPopup,
DispatchFinishPopup,
Keyboard: () =>
import(
/* webpackChunkName: "keyboard" */
'@/components/numberplate/vnp-keyboard.vue'
),
},
}

还有 特别大的第三方库 echart 懒加载 按需引入


四、总结


目前通过禁用预加载、路由懒加载、和第三方组件懒加载使用方式 基本能达到很大程度的优化效果。


但是看图 每次加载前面2个文件一个683k 另外一个285k 还是压缩了的文件 ,


我猜应该是main.js 引入了很多东西,后续还可以有优化空间。移动端的h5 入口文件尽量简洁。



(自己写的页面 一定多注意看一下 网络 有多少个js 和css 图片) 资源过大就要考虑优化了。


性能优化一定要多测试验证、多测试验证、多测试验证,保证业务正常情况下优化性能。


性能优化参考。


juejin.cn/post/718889…


作者:德哥0904
来源:juejin.cn/post/7572301616168583177

0 个评论

要回复文章请先登录注册