在这以前虽然看过一些博客介绍 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 remote
。java
咱们常见的智能零售或者说其余的智能硬件的交互屏,通常是一个相似 树莓派 的板子,而后装载系统。能够是 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 初始化会后,页面都是按照以下处理业务
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 才会刷新,这个断开操做可能会干扰到用户操做。
对于 app 来讲有一个用户重启 app 的概念,咱们也能够加一个这个功能,机器会断电,断电后能够更新或者线下运维人员能够在运维的时候重启一下。
还有一种方案就是服务向最近10分钟无状态的机器推送消息,机器收到消息后强制刷新页面。
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 协议头来传递,直接设置 http 协议头不是也能够解决问题吗
强缓存
协商缓存
详细学习能够参考资料HTTP 缓存机制一二三
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天或者半天就能完成的工做,剩下的时间让你加班你是否是能够继续折腾了?但这些都须要创建在基础服务完善的基础之上,没事的时候就完善通用组件,工具函数,基础样式类等,相应的服务端也须要配合演进,不断打磨中才能更好的完善稳定。
上去就是干!