在这之前虽然看过一些博客介绍 hybrid,但是始终没有具体应用场景,想象的就是我现在做好了一个网站,然后 native 直接在 webview 中打开我的网站,类似浏览器中打开网站一样,头部添加一个类似浏览器的返回按钮,如果只是考虑到安卓或许这一步都没必要。

以下是以一个面描述了一个点的整个过程。

检索

  • 硬件交互

    • 通讯协议
    • 远程操作
  • 问题分析
    • websocket 心跳重连问题
    • 缓存方案
    • 图片资源渲染问题
    • 系统字体大小修改影响网页字体大小
    • 多小程序扫同一个码的需求
  • 如何进阶

认真接触 hybrid 是在入职后的第一个项目,项目是基于 Hybrid/webapp at gh-pages · yexiaochai/Hybrid · GitHub 其中视图部分在原项目基础上引入了 vue ,目录结构等都是和之前项目一致,页面和组件可以直接使用 vue 语法,hybrid 协议有些许变化。

没有 webpack 项目的启动依赖 Charles map local 预览项目,mock 工具当时使用的是 easy-mock 中间跨域的解决方案是 Charles map remote

硬件交互

我们常见的智能零售或者说其他的智能硬件的交互屏,一般是一个类似 树莓派 的板子,然后装载系统。可以是 win,android,也可以是 ios。开发需要 native 初始化一个 webview,然后定义一些通用协议,加载一个页面似乎就完活了。

通讯协议

开发过程中我们需要 native 赋予我们一些能力,我们需要约定一下通讯协议的格式,其中参数 tagname:协议名称;param:协议参数;callback:协议回掉(native处理成功以后可能需要返回一些参数信息)

格式如下:

{
tagname: '', //
param: {},
callback() {}
}

远程操作

例如用户扫码购买了一瓶饮料,我想在零售屏上切换一个欢迎使用的页面,这个时候需要在 用户-零售屏 上建立关系,这中间可能需要一个服务端。用户一开始和服务端建立联系,正常的下单购买,购买成功后,服务端推送一条消息给零售机,告诉他有用户买了瓶饮料,你现在给他推一个饮料出来。

用户 -> 扫码 -> 购买 -> 服务 -> 出货

用户扫描机器上的二维码,这个行为会触发一个与当前售卖机绑定的操作,绑定成功后服务可以推送一个消息给零售屏,零售屏接收到消息后会切换到欢迎界面,后续的交互包括支付成功,出货成功这些消息如果要表示到零售屏上都是同样的道理。用户与服务,服务与零售屏他们时如何通讯的呢?

用户与服务之间是数据请求,服务与零售之间为了通讯保持,建立的是 websocket 连接,零售机内部是 hybrid ,native 调用硬件能力。

问题分析

开发过程中遇见过一些问题,应该是 hybrid 应用开发也会遇到这些问题,相对而言这些问题对比一个成熟的 hybrid 方案要解决的问题要轻很多。

websocket 心跳重连问题

这个问题是消息推送相关。websocket 初始化会后,页面都是按照如下处理业务

	const ws = new WebSocket('url');
ws.addEventListener('error', e => {
// 去维护页面
}) ws.addEventListener('message', event => {
// 按消息内容处理事件逻辑
}) ws.addEventListener('open', event => {
// 定时发送消息 4min NAT
}) ws.addEventListener('close', event => {
// 去维护页面
}) ws.addEventListener('disconnect', event => {
// 去维护页面
})
  • 单页应用容器内维持状态,组件内展示业务状态。远程操作时提到的服务与零售屏之间的通讯是 websocket ,零售屏中通过监听 message 来调用对应的方法处理相应的逻辑。有指定的故障页面,故障会跳转到故障页面,故障有:机器断网(native捕捉处理),请求超时,服务端主动更新断开,运维维护断开等等情况,如果是 websocket 断开会定时刷新页面重新连接,如果是 websocket 没有断开,数据请求超时等,定时再次请求,如果请求成功切换页面。

这里有另外一个问题,零售屏页面更新的问题,之前是进入维护页面会定时刷新页面,这样如果页面更新下次刷新肯定可以更新到新的页面,现在更改成只有断开 websocket 才会刷新,这个断开操作可能会干扰到用户操作。

对于 app 来说有一个用户重启 app 的概念,我们也可以加一个这个功能,机器会断电,断电后可以更新或者线下运维人员可以在运维的时候重启一下。

还有一种方案就是服务向最近10分钟无状态的机器推送消息,机器收到消息后强制刷新页面。

  • 定时发送业务心跳消息。在这之前没有定时去发送消息,会出现一种情况是受其他原因被关闭了,websocket 并不会监听到关闭或断开或错误,这样就不会去重新连接,这时用户的操作零售屏是收不到任何消息的。服务推送消息是正常推送会提示已经断开。 Pings have an opcode of 0x9, and pongs have an opcode of 0xA 心跳的发送都是底层协议来做的,但是会涉及到一个问题就是NAT超时链路会被断开,这个时候如果业务没有数据传递,客户端不会重新建立连接,如果零售屏没有消息发送就不能出发关闭时间,如果零售机就失联了,按照Android微信智能心跳方案设置了一个业务心跳,维持长链接的活动,这样以来不会触发用户扫码无响应机器失联的情况。

    服务可以根据扫码加推送消息日志来判断有没有具体失联,如果失联可以调整业务心跳的触发时间。

缓存方案

一开始 Native 认为缓存问题很难处理,直接就在配置中没有使用缓存,每次页面加载都会直接重新从线上加载资源(LOAD_CACHE_ONLY),我的每一个状态页面切换也都会耗费资源流量,首页加了一个视频啊,1G的流量卡如何是好?网络不好的情况下如何是好?

搜索发现 android 在 webview 中可以有几种形式设置缓存

// 缓存模式如下:
// LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
// LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
// LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
// LOAD_CACHE_ELSE_NETWORK: 只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

通过 nginx 配置 http 的缓存协议头,可以使用 LOAD_DEFAULT ,通过缓存协议来控制。页面的发布每一次都会根据内容以 hash 的名字命名编译文件,每次发布都能保证修改后的文件会重新从走线上资源拉取。

  • meta标签,浏览器在请求文档资源时会在请求头上携带 content 信息,可以处理缓存问题,但是对于非浏览器缓存的情况下这种形式就失效了
  • meta 标签是走的 http 协议头来传递,直接设置 http 协议头不是也可以解决问题吗
    • 强缓存

      • Expires HTTP/1.0 指缓存过期的时间,超过了这个时间点就代表资源过期
      • Cache-Control HTTP/1.1 指定一个时间长度,在这个时间段内缓存是有效的,单位是s
    • 协商缓存
  • 本地资源缓存,可能我们有时需要更新 app 资源包的形式来更新一些资源,是直接使用 file:// 的形式来读取资源好一些呢?还是直接走 http:// 的形式好一些呢?很明显是后者,如果缓存有,强缓存直接用本地。协商缓存或者缓存没有 native 有直接拦截请求做响应,如果没有,直接走线上请求。

    编译项目以后,项目静态资源可以按需打包到 app 中随 app 的更新升级做升级。

图片资源渲染问题

零售屏的二维码信息时动态更新的,有一个很诡异的bug是二维码偶尔会出现缓存的问题。浏览器渲染机制以及vue内部运行机制,没有深入没有发言权,后续如何提升这也是一些方向。

为了解决图片的缓存的问题,请求的时候我们都会在图片的地址上带上时间戳。诡异的问题描述如下(以下数据都是通过日志记录所得):

1. 生成:11:20:34 130281
2. 生成:11:20:50 399538
3. 生成:11:35:09 123391
4. 使用:11:35:15 123391
5. 生成:11:35:30 117602
6. 使用:11:35:37 399538
7. 使用:11:35:44 399538
8. 使用:11:38:29 399538
9. 使用:11:38:42 399538

11:20:50生成一个二维码,11:35:09生成一个二维码并正常使用,说明渲染争取,11:35:30服务日志记录最新生成的码上的信息和用户上传上来的信息不一致,如果说请求还没响应,图片应该是上一次的正常使用时的情况,不会出现上上次的二维码。代码逻辑时按也许需求去续改src。

<img src="" />

能力有限没能找到问题所在,解决方案不能没有啊,刷新时等待图片加载成功后再插入整个图片元素。不是单纯的更新一个属性,而是整个元素。

系统字体大小修改影响网页字体大小

实际零售屏都是一个标准,这个需求是一个相对而言的伪需求,建立在不会有人去修改系统配置的情况下,如果有要么 native 控制,要么页面用相对尺寸,px 会按照设置的字体受影响。

多小程序扫同一个码的需求

零售对应用户,维护对应运营。运营有一些特殊的权限,不想影响到用户,单独需要做一个小程序,用户端和运维端同时去扫描用户端的小程序,运维端是拿不到任何小程序上的数据信息。

小程序也考虑到了兼容用户之前的二维码的情况,于是有了一个自定义二维码的规则,按照自己的业务规则配置链接,然后生成二维码,无论是微信扫一扫,用户或者运维小程序内部扫一扫都可以拿到二维码上的业务信息,同时为了兼容之前的小程序码的扫码需要做一个扫码收口处理。

如何进阶

这个是我一直在思考的问题,一年前刚刚入职的时候给的目标是一年对比之前的两年,现在看来一年不如一年,之前还能尽量保证按时学习新的知识点,唯一有出入的是现在可以学而实践之。从某些方面来说这一年是没有达到预期的。

沉淀

从入职到现在项目起起伏伏很多次,hybrid 技术方案也有 blade,blade-vue,blade-scripts,react-hybrid,rn(名字我按照自己的实际使用划分),小程序也有使用原生小程序,wepy,mpvue,也从 javascript 也部分到 typescript ,如果只是把自己局限在某一个语言或者某一个框架,这样始终是了解如何使用这个框架,学习从文档开始都可以上手。

Hybrid 从 blade 演进到现在已经是第四个版本了,基本的思想都是在继续沿用,改进的只是技术方案。这也是我想到在实际工作中不能局限某种语言或方案,能想办法把当前工作用的技术方案沉淀下来,延续到以后的工作,不能每一次开局一把刀,装备全靠捡,积累很重要。

基础服务

在不断升级过程中也暴露了一些问题,中间也说明了基础服务的重要性,刚开始时是0,计划的是半年内趋于稳定,后面加班的时候会越来越少,后面发现不加班能解决的问题就是换家工作,差别在于加班时你在做的是什么?

如果是没有沉淀的情况下你可能需要2天,沉淀后1天或者半天就能完成的工作,剩下的时间让你加班你是不是可以继续折腾了?但这些都需要建立在基础服务完善的基础之上,没事的时候就完善通用组件,工具函数,基础样式类等,相应的服务端也需要配合演进,不断打磨中才能更好的完善稳定。

上去就是干!

其他问题

结识hybrid体验这一年的更多相关文章

  1. 利用C#开发移动跨平台Hybrid App(一):从Native端聊Hybrid的实现

    0x00 前言 前一段时间分别读了两篇博客,分别是叶小钗兄的<浅谈Hybrid技术的设计与实现>以及徐磊哥的<从技术经理的角度算一算,如何可以多快好省的做个app>.受到了很多 ...

  2. 浅谈Hybrid技术的设计与实现

    前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹——落地篇 随着移动浪潮的兴起,各种APP层出不穷,极速的业务扩展提升了团队对开发 ...

  3. Hybrid技术的设计与实现(转)

    浅谈Hybrid技术的设计与实现 前言 随着移动浪潮的兴起,各种APP层出不穷,极速的业务扩展提升了团队对开发效率的要求,这个时候使用IOS&Andriod开发一个APP似乎成本有点过高了,而 ...

  4. 浅谈Hybrid技术的设计与实现(转)

    前言 随着移动浪潮的兴起,各种APP层出不穷,极速的业务扩展提升了团队对开发效率的要求,这个时候使用IOS&Andriod开发一个APP似乎成本有点过高了,而H5的低成本.高效率.跨平台等特性 ...

  5. (转)浅谈Hybrid技术的设计与实现

    转载地址:https://www.cnblogs.com/yexiaochai/p/4921635.html 前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hyb ...

  6. 浅谈Hybrid技术的设计与实现【转】

    https://www.cnblogs.com/yexiaochai/p/4921635.html 前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术 ...

  7. Atitit.hybrid混合型应用 浏览器插件,控件的实现方式 浏览器运行本地程序的解决方案大的总结---提升用户体验and开发效率..

    Atitit.hybrid混合型应用 浏览器插件,控件的实现方式 浏览器运行本地程序的解决方案大的总结---提升用户体验and开发效率.. 1. hybrid App 1 1.1. Hybrid Ap ...

  8. hybrid app初体验,和react-native一起飞

    第一次启动了react-native的示例,今天主要把其中遇到的坑与解决的办法分享给大家.如有疏漏.错误还望指正. 首先还是要从hybrid app这个概念说起(如果对于这个过程不感兴趣的同学,可以直 ...

  9. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

随机推荐

  1. jQuery 动态绑定插件livequery的用法

  2. group by 多个字段

    众所周知,group by 一个字段是根据这个字段进行分组,那么group by 多个字段的结果是什么呢?由前面的结论类比可以得到,group by 后跟多个子段就是根据多个字段进行分组 注:下面的例 ...

  3. javascript基础(Array)

    1,join() Array.join(),不改变原数组,将数组中所有元素转换为字符串并连接在一起,返回最后生成的字符串 let a=[1,2,3]; a.join(); // =>" ...

  4. PIL成就你的自信之路

    1.强大的PIL库 在Python中,有一个优秀的图像处理框架,就是PIL库,本博文会分模块,介绍PIL库中的各种方法,并列举相关例子. 学习总结:PIL库可以让我们得到更多的需求,以此来满足我们的需 ...

  5. Golang Go Go Go part2:变量及常量声明

    三.关键字及内置预声明常量.类型.函数 1.关键字 Go有25个关键字,只能用在语法允许的地方,不能作为名称使用,它们是: break          default         func    ...

  6. Raiden Charge

    2017年10月22 周日 这是个元气满满 值得纪念的一天(不好意思走错片场了) 虽然有各种乱遭的客观元素 但我们队确确实实地打铁了 那些我们轻视的 野鸡(误)大学 都在我们前面 都说知耻而后勇 虽然 ...

  7. External Snapshot management

    External Snapshot management Symptom As of at least libvirt 1.1.1, external snapshot support is inco ...

  8. 升讯威微信营销系统开发实践:微信接口的 .NET 封装

    GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至 ...

  9. 【RL-TCPnet网络教程】第17章 RL-TCPnet之UDP通信

    第17章      RL-TCPnet之UDP通信 本章节为大家讲解RL-TCPnet的UDP通信实现,学习本章节前,务必要优先学习第16章UDP用户数据报协议基础知识.有了这些基础知识之后,再搞本章 ...

  10. Java ActiveMQ 讲解(二)Spring ActiveMQ整合+注解消息监听

    对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...