结识hybrid体验这一年

在这以前虽然看过一些博客介绍 hybrid,可是始终没有具体应用场景,想象的就是我如今作好了一个网站,而后 native 直接在 webview 中打开个人网站,相似浏览器中打开网站同样,头部添加一个相似浏览器的返回按钮,若是只是考虑到安卓或许这一步都不必。javascript

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

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

硬件交互

咱们常见的智能零售或者说其余的智能硬件的交互屏,通常是一个相似 树莓派 的板子,而后装载系统。能够是 win,android,也能够是 ios。开发须要 native 初始化一个 webview,而后定义一些通用协议,加载一个页面彷佛就完活了。react

通信协议

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

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

远程操做

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

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

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

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

问题分析

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

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 http-equiv=“pragma" content="no-store" /> meta标签,浏览器在请求文档资源时会在请求头上携带 content 信息,能够处理缓存问题,可是对于非浏览器缓存的状况下这种形式就失效了
  • meta 标签是走的 http 协议头来传递,直接设置 http 协议头不是也能够解决问题吗

    • 强缓存

      • Expires HTTP/1.0 指缓存过时的时间,超过了这个时间点就表明资源过时
      • Cache-Control HTTP/1.1 指定一个时间长度,在这个时间段内缓存是有效的,单位是s
    • 协商缓存

      • Last-modified/If-Modified-Since
      • Etag/If-None-Match

详细学习能够参考资料HTTP 缓存机制一二三

  • 本地资源缓存,可能咱们有时须要更新 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天或者半天就能完成的工做,剩下的时间让你加班你是否是能够继续折腾了?但这些都须要创建在基础服务完善的基础之上,没事的时候就完善通用组件,工具函数,基础样式类等,相应的服务端也须要配合演进,不断打磨中才能更好的完善稳定。

上去就是干!

其余问题

相关文章
相关标签/搜索