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

这篇具有很好参考价值的文章主要介绍了汽车之家主机厂离线化 H5 Hybrid 实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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 Hybrid 架构上,主要分成四大模块:H5 离线包管理工具、APP 开发工具、Native 运行时和 Webview 运行时。

 

4.离线包管理工具

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

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

4.1

离线包发布流程

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

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

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 管理平台截图

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

5.客户端设计

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

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

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%。完成相关方案如下:

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

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

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。

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

 

7.总结

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

 

作者| 主机厂BU-技术部文章来源地址https://www.toymoban.com/news/detail-710385.html

到了这里,关于汽车之家主机厂离线化 H5 Hybrid 实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 汽车之家10年系统架构演进与平台化架构实践

    目录: 一、前言 二、架构演进 1、起步阶段 2、微服务阶段 3、主数据阶段 4、平台化架构阶段 三、平台化架构实践 1、业务身份化 2、服务编排化 3、业务配置化 4、开发工具化 5、数据可视化 6、知识沉淀 四、尾声 1、探索新零售 2、架构升级   一、前言   汽车之家电商系统

    2024年02月06日
    浏览(56)
  • 云原生|kubernetes|centos7下离线化部署kubesphere-3.3.2---基于kubernetes-1.22.16(从网络插件开始记录)

    kubesphere的离线化部署指的是通过自己搭建的harbor私有仓库拉取镜像,完全不依赖于外部网络的方式部署。 我的kubernetes集群是一个单master节点,双工作节点,总计三个节点的版本为1.22.16的集群。 该集群只是初始化完成了,网络插件什么的都还没有安装,本文计划做一个整合

    2024年02月12日
    浏览(42)
  • Hybrid App(原生+H5)开发

    市面上主流的hybrid app框架主要有 React Native:由FaceBook开发,使用JavaScript和React来构建原生应用程序 Flutter:由Google开发,使用Dart语言。Flutter使用自己的渲染引擎 Ionic:基于 Web 技术(HTML、CSS 和 JavaScript),使用 Angular 框架。Ionic 提供了一组 UI 组件和工具,使开发人员能够构

    2024年02月05日
    浏览(40)
  • 基于 prefetch 的 H5 离线包方案

    对于电商 APP 来讲,使用 H5 技术开发的页面占比很高。由于 H5 加载速度非常依赖网络环境,所以为了提高用户体验,针对 H5 加载速度的优化非常重要。 离线包 是最常用的优化技术,通过提前下载 H5 渲染需要的 HTML/JS/CSS 资源,加载时直接使用本地缓存资源避免额外的网络请

    2024年02月08日
    浏览(52)
  • 【从0开始离线数仓项目】——新能源汽车数仓项目介绍

    目录 1、数据仓库概念 2、项目需求及架构设计 3、集群资源规划设计  4、车辆日志字段说明 数据仓库(Data Warehouse)是为企业提供数据支持,用以协助企业制定决策、改进业务流程和提高产品质量等方面的工具。它可以接收多种类型的输入数据,如业务数据、日志数据和爬虫

    2024年02月13日
    浏览(40)
  • 使用H5+app在安卓5.1离线环境实现文字转语音

    在Vue中实现中文文字转语音的方法可以使用HTML5的SpeechSynthesis API,同时需要考虑到在H5+ App里面的离线环境。 在配置文件中正确引入plus库:   在Vue组件中使用SpeechSynthesis API实现中文文字转语音的功能:  

    2024年04月25日
    浏览(33)
  • ​任务编排工具在之家业务系统中应用探究

      本文主要介绍在之家广告业务系统中运用任务编排治理工具的场景及其可以解决的问题,讲解任务编排框架的核心要点,以及向大家演示一个任务编排框架的基本结构,让大家对任务编排工具增强业务开发效率,提高研发质量有更深刻的理解。   1.背景 我们开始以下面的实

    2024年02月09日
    浏览(47)
  • 助力AI语音开发者的社区-语音之家

    语音之家成立于2021年4月,是一家助力AI语音开发者的社区,我们希望通过知识传播、在线学习、资源分享、各类活动等方式提供全生命周期的服务,帮助全球的AI语音开发者获得成长,洞见AI语音技术领域的发展。目前,社区新媒体矩阵,AI语音技术粉丝数量超过5万。 社区平

    2023年04月10日
    浏览(48)
  • 聊一聊GIS之家团队数据案例源码共享以及在线体验

    目录 我们的初衷定位 我们的服务内容 我们的经营模式 GIS之家交流群 我们的未来规划 各平台账号 目前阶段我们团队创建的初衷定位,以服务初学者以及1-2年工作经验的giser为主。利用我们深耕gis行业领域多年gis项目以及工作经验优势,为他们提供地图数据和案例源码共享服

    2024年02月08日
    浏览(32)
  • 【Java之家-编程的衣柜】线程的基础知识及线程与进程的联系

    线程是什么 一个线程就是一个 “执行流”. 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 “同时” 执行 着多份代码. 轻量级进程 - 线程(Thread) 为什么要有线程 首先,“并发编程”成为“刚需” 其次, 虽然多进程也能实现 并发编程, 但是线程比进程更轻量

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包