efte是个啥玩意儿
TRANSCRIPT
Efte是个啥玩意⼉儿?
• Efte 是两栖动物,蝾螈的古称(词源), 发⾳音为 /eft/
• 我们⽤用蝾螈来⽐比喻点评的 Hybrid App Framework
Efte - Hybrid App Framework
每个平台开发代价⾼高昂 我们要write once, run everywhere!
为啥要开发Efte框架
移动端⼈人才短缺!
为啥要开发Efte框架
Native App审核周期太⻓长!
为啥要开发Efte框架
多团队在同⼀一个代码库上发布,噩梦!
为啥要开发Efte框架
PhoneGap
Efte
为啥不⽤用PhoneGap?
• 把native app的特性加到web app
• 把web app的特性加到native app
Efte在点评的使⽤用情况
主App团购和活动阿波罗App 点评管家
让我们来看看Efte的实际运⾏行效果
Native本地静态⽂文件
web前端框架
开发框架
开发⼯工具集
JS标准接⼝口
native端框架
App外壳(可选)
离线包管理
插件库(可选)
导航中⼼心
数据中⼼心Web容器
Efte的客户端部分
local repo
mock server
dev tools
package management
cortex registry
Git
包管理后台
CI
CDN provider
packages
diff&patch
zip
CDN
app
Efte的服务端部分
让我们重点关注创新的两块:
离线包管理解决⽅方案
多⻚页⾯面管理解决⽅方案
—如何让⻚页⾯面加载得更快
—如何让多个⻚页⾯面导航和通信
多⻚页⾯面管理解决⽅方案
如何让多个⻚页⾯面导航和通信
Native Web
JS注⼊入
拦截⾃自定义Url
JSBridge
Javascript和Native的通信
JSBridge - Javascript向Native通信
通信过程
使⽤用⾃自定义Url scheme作为通信途径• [scheme]://params
• Native代码通过拦截Url、解析参数来完成通信• Javascript新开⼀一个iframe,加载⼀一段⾃自定义url
举个栗⼦子:Javascript向Native发起定位请求
var callbackId = callbacksCount++;callbacks[callbackId] = callbackFunction;
var ifr = document.createElement('iframe');ifr.style.display = 'none';document.body.appendChild(ifr);
ifr.contentWindow.location.href =‘js://_?method=location&args={}&callbackId=' + callbackId;
setTimeout(function() { ifr.parentNode.removeChild(ifr);}, 0);
1. Javascript通过iframe发出消息
注意这⾥里的callbackId
- (BOOL)webView:(UIWebView *)web shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ if ([request.URL.absoluteString hasPrefix:[self jsScheme]]) { [self handleMessage:[request.URL queryParams]]; return NO; } if ([request.URL.absoluteString hasPrefix:[self urlScheme]]) { NSDictionary *query = request.URL.queryParams; NSString *unit = request.URL.host; NSString *path = request.URL.path; [self efteOpenUnit:unit path:path withQuery:query]; } return YES;}
举个栗⼦子:Javascript向Native发起定位请求
2. Native拦截Url,并分发请求(以iOS为例)
直接向⻚页⾯面注⼊入Javascript
JSBridge - Native向Javascript通信
iOS • stringByEvaluatingJavaScriptFromString
Android • loadUrl
举个栗⼦子:Native向Javascript返回定位信息
NSString *callbackId = @"1";
NSString *retString = @"{\"status\": 1, \"lng\": 121.427165, \"lat\": 31.222093, \"accuracy\": 5}”;
NSString *js = [NSString stringWithFormat:@"window.Efte && window.Efte.callback && window.Efte.callback(%@,%@);", callbackId, retString];
[self.webView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) withObject:js afterDelay:0];
Native注⼊入Javascript(以iOS为例) 还记得前⾯面js传过来的callbackId吗
调⽤用系统⽅方法注⼊入Javascript
现在来看多个⻚页⾯面之间如何通信
使⽤用场景举例
⻚页⾯面1 ⻚页⾯面2
消息中⼼心
不同⻚页⾯面间的通信通过监听和发布⼲⼴广播来实现
JSBridgeBroadcast
JSBridgeBroadcast
Broadcast
监听⼲⼴广播 发布⼲⼴广播
⻚页⾯面1 注册⼲⼴广播监听 ⻚页⾯面2
发出⼲⼴广播
⻚页⾯面1 收到⼲⼴广播 更新数据 并返回
离线包管理解决⽅方案
如何让⻚页⾯面加载得更快
Web⻚页⾯面的 ⼀一般加载过程
是否有缓存?
打开url
下载Html⻚页⾯面
下载CSS
下载JS
下载图⽚片等 多媒体资源
渲染⻚页⾯面
否
是本地提前缓存
执⾏行JS
使⽤用包管理之后…打开url
渲染⻚页⾯面
加载本地资源
执⾏行JS
Efte的本地包结构 - 以apollo为例
unit-m-home unit-m-customer
unit-m-myunit-m-order
unit-m-contract …
初始安装app的时候就会把静态包部署在⼿手机上
程序会定期检查并更新本地静态包
每个静态包都独⽴立存在
为了安全:
https 多次md5校验 ⾮非对称加密
更新时机:
程序打开时 程序恢复时 切换登录时
包更新流程图
local repo
mock server
dev tools
package management
cortex registry
Git
包管理后台
CI
CDN provider
packages
diff&patch
zip
CDN
app
让我们再来回顾⼀一下Efte的服务端部分
更新请求
下载包
https://developer.apple.com/safari/
模拟器/真机+Safari直接调试• iOS需要在设置Safari栏⺫⽬目中打开调试开关 • Safari在[develop]菜单中会出现设备的选项
Web开发调试 - iOS
https://developer.chrome.com/devtools/docs/remote-debugging#configure-webview
模拟器/真机+Chrome直接调试
• Android版本要求4.4.2及其以上
Web开发调试 - Android
独⽴立开发,独⽴立上线
Efte的优势只需前端技能即可开发移动应⽤用程序
write once, run everywhere
静态包⽆无需审核,可以⾃自动更新、灰度发布
Efte的挑战android的⽣生命周期对页⾯面的影响
javascript和native的通信有⼤大⼩小限制(交互⽅方式所致)
android碎⽚片化导致web view的兼容性问题
Q&A