ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

H5移动端App的五个真实优化策略——从预加载到分页加载的代码实战

H5移动端App的五个真实优化策略——从预加载到分页加载的代码实战 H5移动端App的五个真实优化策略——从预加载到分页加载的代码实战在一个校园APP的H5开发中从首屏加载慢、列表滚动卡顿、图片加载耗流量等一系列真实问题出发总结了五条有效的优化策略。不是概念罗列每条策略后面都有这个APP里实际运行的代码。文章目录H5移动端App的五个真实优化策略——从预加载到分页加载的代码实战一、预加载——先加载数据再显示界面二、懒加载——不是必须马上要的数据晚一点再给三、合并请求——把多次请求打包成一次四、并行——串行改并行操作不再卡顿五、分页加载——手机屏幕小一次不要取太多六、优化前后对比一、预加载——先加载数据再显示界面传统的H5页面加载顺序是显示界面骨架→异步请求数据→数据返回后填充。用户看到的是一闪而过的空白骨架屏。优化的思路是反过来的// js/schoolbus.js——先隐藏数据到位再显示setTimeout(function(){document.getElementById(bus-list).style.displaynone;},1);// ...数据加载、Vue渲染...setTimeout(function(){document.getElementById(bus-list).style.displayblock;},500);页面本质上已经渲染完了只是用户看不到。等到数据填充完毕、DOM更新完成再一次性显示出来——用户看到的就是完整页面没有加载过程。Tab切换也用了同样的思路// js/index.js——启动时预创建5个Tab的WebViewfunctionpreateWebviews(){varplistdocument.getElementById(plist).children;// 启动时预创建过多Webview窗口会消耗时间这里限制仅创建5个for(vari1;iplist.lengthi5;i){varidplist[i].id;id(id.length0)preateWebivew(id);}}functionpreateWebivew(id){if(!preate[id]){varwplus.webview.create(id,id,{top:44px,bottom:53px});preate[id]w;}}// 启动后3秒开始预创建setTimeout(preateWebviews(),3000);用户启动APP后3秒内前5个Tab的WebView已经预先创建好了。切换Tab时不需要plus.webview.create()——直接show()就行瞬间切换。预加载的核心把用户操作→等待变成提前准备好→用户操作→直接拿。代价是启动时多消耗一点资源换来运行时零等待。二、懒加载——不是必须马上要的数据晚一点再给图片是H5页面最大的流量消耗者。一个资讯列表页可能有几十张图片全部加载既耗流量又占内存。自研的图片懒加载逻辑// js/params.jsfunctionlazyload(obj,callback){if(obj.getAttribute(data-loaded)){return;// 已经加载过跳过}varimage_urlobj.getAttribute(data-lazyload);// 生成图片的MD5作为本地缓存文件名varimage_md5md5(image_url);varlocal_image_url_downloads/image/image_md5.jpg;varabsolute_image_pathplus.io.convertLocalFileSystemURL(local_image_url);// 第一步先查本地缓存vartemp_imgnewImage();temp_img.srcabsolute_image_path;temp_img.onloadfunction(){// 本地有缓存直接用obj.setAttribute(src,absolute_image_path);obj.setAttribute(data-loaded,true);obj.classList.add(img-lazyload);}temp_img.onerrorfunction(){// 第二步本地没有在线下载并缓存vardownload_taskplus.downloader.createDownload(image_url,{filename:local_image_url},function(download,status){if(status200){// 下载成功后设置src为本地缓存路径obj.setAttribute(src,absolute_image_path);obj.setAttribute(data-loaded,true);obj.classList.add(img-lazyload);}});download_task.start();}}这个设计的精髓是本地缓存优先——图片下载过一次后存到APP本地文件系统下次加载直接走本地文件不需要再发HTTP请求。MD5去重保证了同一张图片只下载一次。页面中的图片用data-lazyload属性代替src!-- 占位图先顶着滚动到可视区时 lazyload 替换 --imgsrc../images/blank.pngdata-lazyload{{ d[i].titleicon }}onloadlazyload(this)/配合滚动检测只加载在屏幕可视范围内的图片。三、合并请求——把多次请求打包成一次传统的开发习惯是一个API取一个数据源——先调获取菜单分类再调获取资讯列表再调获取个人消息数。三个请求三次网络往返。优化的做法是统一入口元数据路由// js/params.js——全站一个后端端点varserverUrlprojectUrlaction/request;// 所有请求都走同一个URL通过metadata区分业务实体varrequestData{requestData:{opertype:select,fields:{},condition:{where:...,metadata:A_INFO,// 这个字段告诉后端查哪张表pagenumber:1,pagesize:5}},tokenId:...};一次请求取回所有菜单分类然后在前端分发到三个不同的UI区域// pages/news.html——一个请求喂饱三个组件varcatasListg.getMenuCatesInfo();// 只调一次// 同一个数据源渲染三处不同的UIlaytpl(menuTpl).render(catasList.reInfo,function(h){document.getElementById(topMenu).innerHTMLh;// 顶部菜单});laytpl(menuMoreTpl).render(catasList.reInfo,function(h){document.getElementById(menuMore).innerHTMLh;// 更多菜单});laytpl(newsDivsTpl).render(catasList.reInfo,function(h){document.getElementById(news_id_divs).innerHTMLh;// 资讯分类});把多次HTTP往返压缩成一次——网络握手成本从N次降到1次。四、并行——串行改并行操作不再卡顿H5是单线程的但APP环境5 Runtime可以用WebView并行处理。创建所有Tab页面的做法是并行而不是逐个// js/sgrb.js——一次性创建所有Tab WebViewinitTabWebview:function(){varcplus.webview.currentWebview();a.each(document.querySelectorAll(#nav a),function(e,f){vargf.getAttribute(data-href),hf.id;if(gh){vari{top:0px,bottom:54px};varjplus.webview.create(g,h,i);// 循环内并行创建j.hide();c.append(j);}})}不是切换到哪个Tab才创建哪个——启动时一次性全部初始化完成。代价是启动稍慢收益是切换时零延迟。页面渲染也是并行的// news.html——三个模板并行渲染laytpl(menuTpl).render(catasList.reInfo,function(h){...});// 同时laytpl(menuMoreTpl).render(catasList.reInfo,function(h){...});// 同时laytpl(newsDivsTpl).render(catasList.reInfo,function(h){...});// 同时三个laytpl.render()调用是异步的框架内部并行处理不需要等第一个渲染完才渲染第二个。五、分页加载——手机屏幕小一次不要取太多手机屏幕最多显示十几条记录一次请求50条数据——用户根本滑不到最后一页浪费了流量和渲染时间。做法是分页每次只取5条用户滑到底再加载下一批// js/lost/lost.js——分页加载下拉刷新varindex1;varisNotfalse;// 到底标识functionfindList(p){condition.pagenumberp;condition.pagesize5;// 每次只取5条success:function(data){index;// 下一页if(temp.length5){isNottrue;// 数据不足5条说明到底了}}}// mui下拉刷新触发下一页mui.init({pullRefresh:{container:#refreshContainer,up:{callback:function(){findList(index);mui(#refreshContainer).pullRefresh().endPullupToRefresh(isNot);}}}});关键判断逻辑在count 5——当返回的数据不足请求的数量时说明数据到底了。下拉刷新控件收到isNot true显示没有更多数据。六、优化前后对比维度优化前优化后首屏加载骨架屏→加载→填充用户看到空白预加载后直接显示完整页面图片流量列表页全部图片一次性下载只下载屏幕内可见的图片已下载的走本地缓存网络请求多个API分散请求N次握手统一入口一次请求前端分发Tab切换切换时才创建WebView有延迟启动时全部预创建切换零延迟列表分页一次取50条大部分浪费每次取5条到底再加载这五条策略的核心不是技术多高级——是一个原则把准备动作提前把不必要的动作延后把多个动作合并让独立的动作同时进行。在手机有限的屏幕和网络条件下这个原则比任何框架选型都管用。
返回列表