说起webview与h5,对整个移动开发业界的人来讲,都是又爱又恨。爱其功能强大、可动态发布、又多端复用。。。又恨其加载慢、响应慢、体验不佳。慢、慢、慢的问题,往往让开发挠头、让客户骂娘!天使与恶魔的共同体,好的坏的都那么明显。
业务快速迭代,h5页面往往承担着一家公司的大部分流量来源,这对有赞也不例外。优化h5的加载,提升客户体验,收益和价值都是巨大的。
要提升h5的加载体验,首先要弄清楚的是,到底是什么影响了h5的打开速度。这是一个系统性的问题,涉及到移动端、前端、后端多个领域、整条链接的加载优化。本文将只聚焦于从移动端的角度怎样做优化。
WebView.loadUrl(url)
讲起当我们开始加载一个网页,从调用WebView.loadUrl(url)
开始,系统到底做了哪些事情,各个阶段的消耗情况如何? 从移动端的角度来看,一个网页的加载过程总体分为上图所示的几个步骤,每个步骤消耗的时间累积影响整体的加载速度。
我们对于有赞的的一些典型h5页面做了各阶段的测试(在wifi条件下),总结如下表:
阶段
耗时
说明
webview初始化
约100ms~250ms
首次需加载webview内核耗时
dns解析+tcp连接
20ms~1.5s
波动较大,最差的情况遇到过1.5s的case
html下载
约200ms~600ms
多数情况400ms左右(wifi)
html解析
100ms~150ms
静态资源下载
50~200ms
此为同步资源消耗,异步资源未计
从直观的角度讲,当打开一个h5页面的时候,页面会有较长时间的白屏——此所谓响应慢。反应到上图的系统过程中,它包括:webview内核初始化(首次打开)、DNS解析及建连、请求html并下载、解析html及同步资源这几步。我们把这个过程记为白屏时间。白屏时间在h5页面加载的前半程,对整体的体验影响最大。
而页面的整体加载时间,还包括异步资源、数据请求的完成,往往是在当前页面已经可看、可操作的后台继续进行着。对用户的体验影响较小(除非首屏有大块区域需要这种异步资源或者数据请求作展示,比如:有赞的商品详情页顶部大部分是商品轮播图)。
从上述表格来看,页面整体的加载过程在1.2s左右,白屏时间至少400ms~800ms。这是在wifi条件下测得的数据,换成移动网络2G/3G,情况会更糟!
清楚了各个阶段的消耗,以及对体验影响最大的白屏时间。从以下方面入手:
这里指webkit内核的初次加载,包含java类的load、动态库查找load到内存中,也包括webview的创建。可考虑的一个做法是,应用启动时全局加载webview内核,以空间换时间(此法大约有10M左右的内存占用)。
DNS解析情况好的时候,几毫秒、十几毫秒就完成了。差的时候,可能需要花很多时间(遇到过需要1.5s的case)。域名收敛、对DNS做prefetch, 尤其对优化一些长尾case非常有用。
如果对css/js、图片、或者其他如ttf等静态资源,预先缓存到本地,可以省去从远端拉取静态资源的消耗。在我们的解决方案中,对于初次、二次打开页面,静态资源的命中率都可以做到80%~100%。
但是必须清楚,除了那几个解析渲染首屏html必要的、同步的静态资源(css/js), 提升静态资源的命中率整体对于白屏时间的优化是比较有限的。静态资源的加载大多是在页面加载的后半程。
从上面数据可以看出,下载html内容的消耗在400ms左右,这是白屏时间的一大来源。如果能缩减这部分时间,则可以大大减少白屏。将html内容提前下载到本地,WebView.loadUrl(ur)
时直接从本地加载,速度要快得多。
但html本身是常变化的,如果本地缓存的html内容过期了怎么办?
如果html的内容是用户相关、需要登录才能看的怎么办?
不过,html的预取、缓存虽然有诸多限制,但并非没有适用的场景!
在有赞的webview加速解决方案中,通过对可缓存的html范围做限制,解决了店铺首页、活动页的h5打开提速问题。这些页面都是属于变化较少、并不私有的页面。
更重要的是:这些页面,往往都是webview的入口页(从native到webview),是最可能产生白屏的地方。进入这些页面后再点击跳转到其他页面属于webview内跳转,其体验尚可。
有赞h5页面中的资源整体要分成两种:
一种是有赞统一资源,这指的是页面共有的css/js等资源,属于有赞的页面都可能会使用;
另一种商家特有的差异资源,只有在这个商家的店铺当中才会用到,这部分主要是商家上传的商品图片。
举几个实例:
类型
路径
说明
有赞统一资源
/v2/wscwap/build/css/showcase/goods_c84308e66177da54cc8371e5d9f65767.css 、 /v2/build/wap/ump/send_coupon_f4f485ecf5.js
商家差异资源
/upload_files/2017/12/14/FlF05IkscTy9TACqGg129U8Kqxex.jpg?imageView2/2/w/980/h/980/q/75/format/webp
假如有赞的两个商家A和B,分别有自己的店铺或客户端。商家A和B都会共同用到有赞的一些基础css/js静态资源。但A、B各自的商品图片等静态资源是相互隔离的。
除了共用的基础css/js等静态资源,在A的端中只能缓存自己的图片资源,B的端也同样只需缓存B自己的图片资源。
这里有必要解释一下“商家的端”的概念及具体形式:拿有赞典型的两个产品来说,一个是微商城,一个是App开店。在微商城客户端中,商家A和B分别用自己的帐号登录、管理自己的店铺,这里,商家的端=微商城客户端+A/B的店铺。
而在App开店中,有赞提供一个基础的AppSDK,包装有赞的商品系统、营销系统等后台服务,商家A和B在自有的客户端App中集成这个基础SDK,就可以使用有赞的服务。这里,商家的端=商家A/B自有的app+AppSDK
不同的商家的端,所需要的资源是不相同且必需隔离的。这一特点会影响到我们后面的系统设计。
做静态资源缓存的一大要点是如何解决资源变化后的实时更新问题?以及系统如何自动发现资源已经变化?变化后如何更新缓存?
我们的前端每天都在发布,每天都有一定数量的css/js等需要更新。 我们的商家们每天都在做生意、上传新的商品,每天都在添加新的图片。
对于css/js等一类资源,我们采用webpack
打包,资源内容的变化就一定会引起资源路径变化。比如:/v2/build/wap/ump/send_coupon_f4f485ecf5.js
这个资源,它的后缀部分f4f485ecf5
其实是这个资源文件的md5值前10位。
对于图片类的资源,每次上传图片,它也会有一个唯一的路径。比如:/upload_files/2017/12/14/FlF05IkscTy9TACqGg129U8Kqxex.jpg
。
变化后的资源 => 不同的路径, 这个特点对于解决如何发现变化、缓存实时更新的问题真是有太多的方便!
有赞的html页面有很多种,各有特点:有的变化很快,有的属于隐私页面。但也有一些相对稳定的入口页、活动页。
html的加速,除了从html获取的全链接下手(包括服务器、业务方、协议层等),单就做html缓存预取来说,其实是相当难做的。因为实时性的问题,难以解决。尤其有赞的html页面并未做前后端分离。它的所有页面内容,包括一部分页面数据都是在服务器端中拼接直出的。
从之前的数据分析,html内容的获取是占白屏时间的大头。所以对它做优化是项目是否取得显著成效的关键。但是如果把前后端的同学聚集起来做大幅度的改造:前后端分离、优化协议。。。恐怕长期也难见成效。业务的发展和成长是第一位的。
如果我们把要优化html页面的范围缩小,聚焦于那些相对稳定的微页面/店铺首页、商品详情页、活动页,我们可以牺牲一点点的实时性,来换取加载体验极大提升。而恰恰这些页面往往是webview的入口页,也是访问最多的页面。对它们的加载做优化,可以得到最佳的投入收益比。
初看这个名字可能会觉得很怪,它很中国化,英文代号也很拉风。金翅是一种常见的鸟,我们寄寓这套系统能给我们的app带上翅膀。
金翅是我们对有赞移动端h5加速解决方案的总称,它包括Android/iOS客户端sdk、java后台服务、还有nodejs写的管理控制台。
在这套系统中,我们解决了以下几个问题: * 有赞所有静态资源的缓存,包括统一的css/js等资源,及商家端特有的图片等资源; 店铺首页/微页面、商品详情页、活动页等入口页的html加速; 动态化配置、在线接入及管理。
在不约束下载条件(如:wifi)的情况下,不论是首次、二次以后打开页面,静态资源的命中率达到了80%~100%。
对于html的加速优化前后,请看如下动图对比: * 不使用优化
效果还是还当的明显的!未使用优化的第一张图,可明显看出有较长时间的白屏效果。而使用优化后的第二张图,效果已经可以近于native化的加载体验了。
关于金翅如何做静态资源的缓存?如何做html的加速、缓存预取?后文将单独做专题讲述。
做这套h5加速解决方案,前后时间大概有三个月之久。这期间小组内同事们除了要继续做手头的业务,其他大部分的精力都投入了这项工作当中。
这期间我们参考了业内许多其他公司同仁的分析、思考与总结,结合有赞业务的特点完成了这套h5加速解决方案。
目前这套体系稳定的接受着千万级流量的洗礼,我们同时也在公司内的更多业务线中推广铺开。
欢迎关注我们的公众号
Original url: Access
Created at: 2019-09-26 18:05:56
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论