共计 2669 个字符,预计需要花费 7 分钟才能阅读完成。
什么是 hybrid
hybrid 即“混合”, 即前端和客户端的混合开发
需前端开发人员和客户端开发人员配合完成
某些环节可能涉及到 server 端
hybrid 存在价值
可以快速迭代更新(无需 app 审核)
体验流畅(和 NA 体验基本类似)
减少开发和沟通成本, 双端公用一套代码
webview
是 app 中的一个组件(app 中可以有 webview, 也可以没有)
用于加载 h5 页面, 即一个小型的浏览器内核
file 协议
浏览器打开本地文件, 就是通过使用 file 协议
file 协议: 本地文件, 快
http(s)协议: 网络加载, 慢
使用场景
使用 NA: 体验要求极致, 变化不频繁(如头条首页)
使用 hybrid: 体验要求高, 变化频繁(如头条的新闻详情页)
使用 h5: 体验无要求, 不常用(如举报, 反馈等页面)
具体实现
前端做好静态页面(html,js,css), 将文件交给客户端
客户端拿到前端静态页面, 以文件形式储存在 app 内
客户端在一个 webview 中
使用 file 协议加载静态页面
hybrid 更新上线流程
分版本, 有版本号, 如 201803211015
将静态文件压缩成 zip 包, 上传到服务端
客户端每次启动, 都去服务端检查版本号
如果服务端版本号大于客户端版本号, 就去下载最新的 zip 包
下载完之后解压, 覆盖原有文件
hybrid 和 h5 的区别
hybrid 优点:
体验更好, 跟 NA 体验基本一致
可快速迭代, 无需 app 审核
hybrid 缺点:
开发成本高: 联调, 测试, 查 bug 都比较麻烦
运维成本高
适用场景
产品都稳定功能, 体验要求高, 迭代频繁. 产品型(hybrid)
单次运营活动 (如 xx 红包) 或不常用功能. 运营型(h5)
schema 协议 — 前端和客户端通讯的约定
网上搜的微信部分的 schema 协议
weixin://dl/scan 扫一扫
<!– 以下是演示, 无法正常运行, 微信有严格的权限验证, 外部页面不能随意使用 schema–>
function invokeScan() {
var iframe = document.createElement(‘iframe’);
iframe.style.display = ‘none’;
iframe.src = ‘weixin://dl/scan’; // iframe 访问 schema
var body = document.body || document.getElementByName(‘body’)[0];
body.appendChild(iframe);
setTimeout(function(){
body.removeChild(iframe); // 销毁 iframe
iframe = null;
});
}
document.getElementById(‘btn’).addEventListener(‘click’, function(){
invokeScan(); // html 调用 schema 协议
})
// 如果要加上参数和 callback, 那么就要这么写
window[‘_weixin_scan_callback’] = function(result) {
alert(result);
}
// … 省略 …
iframe.src = ‘weixin://dl/scan?k1=v1&k2=v2&callback=_weixin_scan_callback’;
// … 省略 …
封装 schema
voke.js
(function (window, undefined) {
// 封装 schema
function _invoke(action, data, callback){
// 拼装 schema 协议
var schema = ‘myapp://utils/’ + action;
// 拼装参数
schema += ‘?a=a’;
for(key in data){
if(data.hasOwnProperty(key)){
schema += ‘&’ + key + ‘=’ + data[key];
}
}
// 拼装 callback
callbackName = ”;
if(typeof callback === ‘string’){
callbackName = callback;
} else {
callbackName = action + Date.now();
window[callbackName] = callback;
}
schema += ‘callback=callbackName’;
// 触发 schema
var iframe = document.createElement(‘iframe’);
iframe.style.display = ‘none’;
iframe.src = schema;
var body = document.body;
body.appendChild(iframe);
setTimeout(() => {
body.removeChild(iframe);
iframe = null;
});
}
window.invoke = {
share: function (data, callback) {
_invoke(‘share’, data, callback);
}
}
})(window);
index.html
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<title>Document</title>
</head>
<body>
<button id=”btn”> 分享 </button>
</body>
<script src=”voke.js”></script>
<script>
document.getElementById(‘btn’).addEventListener(‘click’,function(){
window.invoke.share({
titile:’111′,
content:’2222′
}, function(res){
if (res.status){
alert(‘ 分享成功!’);
} else {
alert(res.message);
}
});
});
</script>
</html>
内置上线
将以上封装的代码打包, 叫做 invoke.js, 内置到客户端
客户端每次启动 webview, 都默认执行 invoke.js
本地加载, 免去网络加载都时间, 速度会更快
本地加载, 没有网络请求, 黑客看不到 schema 协议, 更安全