首页 > 其他分享 >汽车之家主机厂离线化 H5 Hybrid 实践

汽车之家主机厂离线化 H5 Hybrid 实践

时间:2023-10-04 19:47:04浏览次数:43  
标签:主机厂 string 离线 APP Hybrid H5 请求

1.背景

H5 页面做秒开优化是业务的常规操作,一般正常通过网络请求的 H5 页面,我们都是围绕资源加载速度优化展开。优化手段主要分两个方向,一个是提升网络速度,一个是减少资源大小。

提升网络速度,一般的手段有 DNS 预解析、多域名、升级 HTTP2、使用 CDN、SSR。而即使有静态资源的网络缓存,HTML 也只能用协商缓存,需要消耗一次网络请求。这也注定了无法避免因网络问题导致的页面白屏时间较长的问题,在我们真实的数据中也能得到印证,无论怎么优化,页面的 1.5 秒开稳定在 90% 以上非常困难。

因此,如果想实现 95% 以上甚至 99% 以上秒开,离线化 H5 是必然的选择。同时根据历史经验,随着 iOS 和 Android 手机的性能不断提升,Webview 的渲染性能也不断提升,目前大部分手机的 H5 离线化渲染都可以实现无白屏体验,无限接近原生的交互体验。

 

2.收益

在实践过程中,我们分两个场景构建离线化 H5 基座,一个是由 H5 开发的新 APP,一个是汽车之家 APP。

主机厂内部有一个应用,第一版是 Native 和 H5 的混合开发,会通过网络请求资源,虽然有网络缓存,但是第一次打开也很慢,非常影响用户体验,内部性能监控平台显示首屏平均耗时 1s。后面全面改造成内置离线 H5 应用,Native 只提供桥功能,首屏平均耗时减少到 237ms,加载速度提升 4 倍,大部分情况下实现无白屏体验。业内曾经做过人眼识别白屏的最小时间测试,当降到 200ms 左右时,人眼几乎无法识别白屏。

新 APP 我们主要使用 H5 开发,而不是用 Flutter 或者 RN 等技术,最主要的原因是人才储备不足,在业务场景并没有特别复杂的原生体验情况下,我们发现业务迭代,对客户端的依赖大大减少,沟通成本降低,迭代效率有明显提高,团队不需要面对复杂的 Flutter 和 RN 引擎,也不需要熟悉客户端的开发模式。

汽车之家 APP 中,由于历史原因,不能预置离线包 H5,所以只能有选择性地进行动态预加载,而这会导致在开屏等特殊场景下,访问速度仍然不高。整体上首屏时间从 1240.4ms 缩短为 505.4ms,加载速度提升一倍。

 

3.技术架构

图片

 离线化 H5 Hybrid 架构上,主要分成四大模块:H5 离线包管理工具、APP 开发工具、Native 运行时和 Webview 运行时。

 

4.离线包管理工具

H5 离线包管理工具包含:离线包管理平台、之家云打包脚本。离线包管理平台包含:APP 应用管理、H5 应用管理、发布回滚、开关控制四大功能。通过和之家云发布流水线联动,可以实现网络版和离线版 H5 的版本同步,发布操作也实现同步,由于之家云功能限制,回滚目前还不支持联动。

管理的物料包括:H5 离线包(H5 代码、离线包配置文件)、APP 离线包配置文件。APP 配置文件,在没有预置离线包的情况下,下载资源是阻塞性的。为了提升下载速度和可用性,APP 配置文件也被维护成了一个 CDN 上的 JSON 文件。

4.1

离线包发布流程

在之家云发布平台,使用离线包管理 CLI 工具,执行上传离线包命令,并配置一个离线包发布的 Webhook,即可实现自动化离线包发布。离线管理平台会同步之家云平台的离线包版本号。

图片

4.2

离线包设计

和普通的 H5 打包文件相比,离线包新增了一个专属的离线包配置文件 config.json,同时会把资源打包成 gzip 压缩包,从而提升整体资源的下载速度。

资源目录

h5id
├── js/
├── css/
├── img/
├── pages
│   ├── index.html
│   └── list.html
└── config.json(配置文件)

配置文件

interface HybridConfig {
  // 离线 H5 APP ID
  h5id: string;
  // 匹配页面和静态资源的规则
  mapping: {
    [env: string]: {
      pages: Resource[];
      resources: Resource[];
    }
  };
  package: {
    // 离线包资源目录路径,根目录相对路径
    file: string;
    // 包含的文件,和 excludes 互斥,只能同时有一个
    includes: {
      ext: string[];
      file: string[];
    };
    // 不包含的文件
    excludes: {
      ext: string[];
      file: string[];
    };
    // Native APP 版本适配
    appRules: {
      // 离线包管理平台的应用 ID
      [appid: string]: {
        // [最小版本,最大版本]
        ios: [string, string];
        android: [string, string];
      }
    };
  }
}

interface Resource {
  // 拦截到的请求 url 的规则,不提供 http 或者 https,支持单个文件和文件目录。
  // 例如:example.com/page,example.com/static/img.png
  remoteUrl: string;
  // 和 downloadUrl 必须有一个存在,相对离线包所在目录的文件路径。
  // 「path」值会替换掉请求 url 中的「remoteUrl」字符串。
  path?: string;
  // 和 path 必须有一个存在,指定下载资源的 url,
  // 下载后存放在离线包的 vendor 目录下。
  // 并把存储 path 同步到配置文件的 path 字段。
  downloadUrl?: string;
  // 可选的 mime type,如果不提供,通过文件名后缀自动补偿
  contentType?: string;
}

 

4.3 

打包命令行工具

  1.  打包发布脚本发布到之家私有源,以脚手架命令形式调用,提供打包、上传命令;

  2. 业务方结合自身编译上线流程进行调用,上传完成则自动进行发布;

  3.  前端静态资源按照页面/工程纬度打包成zip;

  4. zip包含js/css/img/pages/config.json配置文件;

// 脚本安装
npm i @auto/dt-fe-cli

// 编译上传
// 指定脚本的配置文件,打包并上传至服务器,默认配置文件为 config.json,可以使用 --config 指定配置文件
dt-fe-cli offline --config hybrid-config.json

 

4.4 

管理平台

为了更好管理离线包,我们提供了一个简洁的管理后台,用来管理 H5 应用和 APP 应用的关系,记录之家云编译好的离线包,同时提供 APP 配置给客户端查询。为了提高 APP 配置下载速度和可靠性,我们用 CDN 上的 JSON 文件来存储 APP 配置。

►4.4.1 APP 配置

interface APPConfig {

  appid: string;
  version: string;
  updateTime: string;
  isIosEnable: boolean;
  isAndroidEnable: boolean;
  H5Apps: H5App[];
}

interface H5App {
  // H5 应用的 APP ID
  h5Id: string;
  versions: H5Config[];
  lastVerison: {};
  latestUrl: string;
}

interface H5Config {
  version: string;
  // true,开启离线化
  isEnable: boolean;
  // true,开启 iOS APP 离线化
  isIosEnable: boolean;
  // true,开启 Android APP 离线化
  isAndroidEnable: boolean;
  // true,需要预先加载
  isPreLoad: boolean;
  pages: Resource[];
  appRules: AppRules;
  downloadUrl: string;
}

interface Resource {
  // 拦截到的请求 url 的规则,支持单个文件和文件目录。例如:/page,/static/img.png
  remoteUrl: string;
  // 和 downloadUrl 必须有一个存在,相对离线包所在目录的文件路径。
  // path 会替换掉请求 URL 中的「remoteUrl」字符串
  path?: string;
  // 和 path 必须有一个存在,指定下载下载资源的 url,下载后存放在离线包的 vendor 目录下。
  // 并把存储 path 同步到配置文件的 path 字段。
  // 下载失败,则该匹配规则失效自动访问网络资源
  downloadUrl?: string;
  // 可选的 mime type,如果不提供,通过文件名后缀自动补偿
  contentType?: string;
}

interface AppRules {
  // ios APP 的开始和结束版本,最大版本可设置 infinite
  ios: [string,string];
  android: [string,string];
}

 

4.4.2 管理平台截图

图片
图片
图片

5.客户端设计

作为整体 Hybrid 离线包应用架构中的重要一环,端内 Hybrid 离线包 SDK 包括 Webview 管理、离线包管理、Bridge 三个模块。

图片

5.1 

Webview管理

  1. 定制 Hybrid 浏览器,设置可通过特定 Scheme 协议打开;

  2. 如果没有离线资源,可以降级 HTTP 请求,也可以选择阻塞下载;

  3. 通过 H5 应用映射表匹配当前页面 Url 和缓存资源,存在缓存资源时,Hybrid 浏览器拦截 H5 所有资源请求,执行本地缓存逻辑:命中缓存时直接返回本地资源;未命中缓存则交还给WebView进行默认处理;

  4. 关闭 Hybrid 浏览器时触发离线包管理逻辑,进行资源更新。

5.2 

离线包管理

  1.  APP 预置:APP 打包时可以使用命令行工具批量下载需要预置的离线包,并集成到 APP 中;

  2. 预加载:有时候出于 APP 体积的考虑,我们不能预置所有离线包,为了提高离线包的加载体验,可以开启预加载,在 APP 启动后的空闲时间主动进行离线包下载;

  3. 更新:根据唯一性原则,同一个 H5 应用同时只保留一份离线资源;

  4. 磁盘空间管理:及时删除下载失败或已解压完成的 ZIP 包;清理旧版本离线资源;结合 LRU 算法进行离线包缓存上限管理。

  5. 环境隔离

5.3 

环境区分及降级处理

  1. H5 应用区分测试、生产环境,不同环境匹配不同离线资源;

  2. 通过预支的字段开关可以控制是否启用离线包逻辑,开关关闭时直接使用线上资源。

5.4 

Hybrid 离线包方案的下一步规划

Hybrid 方案在预加载模式下取得了较好的效果,有效的提升了 H5 页面的秒开率,后续将在以下几个方面继续提升 Hybrid 方案的能力,更好的为主机厂相关业务助力。

  • 增加并完善预置离线包能力:在 APP 大小可控的前提下,在 APP 内预置关键页面的离线包,弥补预加载逻辑在第一次打开时命中率低的不足。APP接入预置离线包后,页面第一次打开时预计资源命中率提高到100%。完成相关方案如下:

图片
  • 增加 One Shot 能力(类小程序):支持在 Hybrid 浏览器首次访问 H5 应用时,实时下载离线资源包并匹配离线资源。APP接入One Shot 能力后,页面第二次打开时预计资源命中率提高到100%。相关方案如下:

图片

6.踩过的坑

6.1 

Post 请求丢失 Body

 iOS 系统,浏览器拦截协议有 NSURLProtocol 和 WKURLSchemeHandler 两种,并且都存在 Post 请求丢失 Body 的问题,针对 Post 请求都需专门处理。

开始时使用的是 NSURLProtocol 协议,优点是可挑选处理请求,不需要处理的可抛回浏览器,但是在特殊场景下出现问题:NSURLProtocol 是全局拦截,打开后所有浏览器都会进行拦截,所以在多个浏览器同时存在,并且非Hybrid浏览器还有发送 Post 请求时,Post 请求 Body 会丢失,导致请求失败。NSURLProtocol 的全局拦截问题无法解决,于是又将目光移向 WKURLSchemeHandler,开始了完全自己实现Http请求。

6.2 

无侵入式拦截

 WKURLSchemeHandler 需要解决的问题有很多,包括Cookies,重定向,Post请求支持等。最开始沿用了NSURLProtocol Post 请求处理方法,业务方将Post请求通过桥的方式,扔给Native进行请求,但紧接着就遇到另一个问题:需要业务方配合改造。作为一个通用平台,接入成本过高是一个致命问题,直接影响业务方接入的意愿。

实现无侵入式拦截,是我们必须要解决的问题,最终通过多次实验,采用了JS注入拦截的方式,具体流程主要为以下几点:

  • 若命中离线,加载网页时开启Handler拦截,注入 Fetch /  XMLHttpRequest 拦截请求脚本;

  • 发送请求时,Post请求通过Bridge发送给Native,Get请求又传递给原生应用进行存储处理WKURLSchemeHandler;

  • Handler拦截的请求若命中离线,走本地资源匹配,匹配到后模拟请求返回H5,未命中时Native发送请求;

  • Post请求,Native通过桥拿到url和Body信息,通过原生请求发送,结果透传给H5。

图片

 

7.总结

随着移动设备整体性能的持续提升,离线化 H5 Hybrid技术架构在加载和交互体验方面取得了显著改善。在许多标准应用场景中,它能够提供接近原生应用的用户体验。此外,它的跨平台、低成本、充足的人才资源、丰富的生态系统和动态更新等优势,使其在与其他跨平台解决方案的比较中脱颖而出。

 

作者| 主机厂BU-技术部

标签:主机厂,string,离线,APP,Hybrid,H5,请求
From: https://www.cnblogs.com/88223100/p/Practice-of-Offline-H5-Hybrid-at-Autohome-Main-Engine-F

相关文章

  • 汽车之家主机厂离线化 H5 Hybrid 实践
    1.背景H5页面做秒开优化是业务的常规操作,一般正常通过网络请求的H5页面,我们都是围绕资源加载速度优化展开。优化手段主要分两个方向,一个是提升网络速度,一个是减少资源大小。提升网络速度,一般的手段有DNS预解析、多域名、升级HTTP2、使用CDN、SSR。而即使有......
  • 论文解读:HybridCR: weakly-supervised 3D point cloud semantic segmentation via hybr
    HybridCR:weakly-supervised3Dpointcloudsemanticsegmentationviahybridcontrastiveregularization基于混合对比学习正则化约束的增强方法,Li等人(2022a)使用极少标注(0.03%)在室内点云数据集上获得的分割精度为全监督方法的78.3%。是第一个利用点一致性并以端到端方式采用......
  • Android开发笔记[6]-离线中文TTS
    摘要在Android上实现离线中文TTS语音播报.源码地址[https://gitee.com/qsbye/AndTheStone/tree/compose]Releasev0p1中有工程压缩包平台信息AndroidStudio:ElectricEel|2022.1.1Patch2Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-......
  • 内网离线安装docker并配置使用nexus为docker私服
    背景本文简单记录下最近在内网服务器离线安装docker及配置nexus作为docker私服,踩的一些坑。docker和k8s这块技术我跟得不是很紧,18年的时候用过一阵docker,后来发现它并不能解决当时我们遇到的问题,后来就没用了,再一个就是,在宿主机上啥命令都有,也太爽了,反观docker里面啥命令都没有,痛......
  • 离线与在线
    1、CDQ分治与树套树CDQ分治本质是仍然是alogb和a+b的分治转化。2、整体二分与树套树整体二分可以看做是树套树上做dfs,或者树套树套树(矩阵第k大)上做dfs。3、树套树与主席树主席树更像是对于特定的可差分/可叠加问题,用前缀和差分/猫树分治的方式,解决这类问题,树套树则有着更......
  • sealos 离线安装k8s
    目录1.修改主机名2.添加主机名与IP地址解析3.升级服务器内核,时间同步,关闭防火墙,重启服务器4.sealos安装5.离线环境安装,离线环境只需要提前导入镜像5.1加载离线包部署6.kubernetes集群可用性验证7.扩展安装8.sealos版本3.3-基本命令1.修改主机名hostnamectlset-hostnamek8s-m......
  • MySQL-5.7版本官方文档二进制离线安
    官网二进制包脚本安装#!/bin/bash#解决软件的依赖关系yuminstallcmakencurses-develgccgcc-c++vimlsofbzip2openssl-develncurses-compat-libs-y#解压mysqql二进制安装包tarxfmysql-5.7.43-linux-glibc2.12-x86_64.tar.gz#移动mysql解压后的文件到/usr/l......
  • 如何搭建一个纯离线的nexus3
    Maven篇0.在离线的nexus3服务器上创建所需的本地依赖仓库。(如果已经创建了依赖仓库文件夹,这个步骤可以忽略)-登录具有创建仓库权限的用户,这里使用默认用户admin示范。创建新的仓库选择hosted格式的maven2仓库选择允许依赖的要求,其他默认1.准备所需的依赖文件-主体的思想......
  • Linux CentOS 7.x离线安装PostgreSQL操作手册
    一、准备环节rpm-qa|greppostgres检查PostgreSQL是否已经安装rpm-qal|greppostgres检查PostgreSQL安装位置postgresql-12.2.tar.gz二、Pgsql数据库安装下载下载地址:http://www.postgresql.org/ftp/source/选择你你需要的版本,本次安装12.2的版......
  • Centos yum 下载全量依赖 rpm 包及离线安装
    简介通常生产环境由于安全原因都无法访问互联网。此时就需要进行离线安装,主要有两种方式:源码编译、rpm包安装。源码编译耗费时间长且缺乏编译环境,所以一般都选择使用离线rpm包安装。操作系统Centos7.9查看依赖包可以使用“yumdeplist”命令来查找rpm包的依赖列表。例如......