浅谈混合应用的演进

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

前端想要写 APP

开篇想以这样的方式开头,从 APP 开始火到现在,前端同学就一直想要写 APP,各方技术也是为了让前端同学写上 APP 操碎了心。

为什么要前端同学来写 APP,站在整个技术链上来看,都是在做页面呈现,页面交互,对于技术而言只是将产品在不同的端上进行呈现,所以很早之前就有提倡说大前端的概念。既然功能都差不多,就没有分家的理由。

再者,开发客户端现在的常规平台有 iOS 和 android 两个大的平台,在前端领域越来越细分的大环境下,传统意义上的客户端开发至少需要两拨开发者来做,成本就会有增加。并且伴随着成本增加还带来了需要两套体系化的语言开发,开发效率也会大打折扣。相较于两大客户端平台的开发人员,前端的开发人员是要更多的,并且随着移动端的兴起前端开发者会有资源剩余的情况,前端来写 APP 也可以平衡资源。

所以不仅仅是前端同学想要来写 APP,更多的是未来发展需要这样的技术来提高生产力,所以才会有各种各样的方案出现,各种方案的诞生也发现了前端写 APP 的不足,所以又有了不断的演进来适应未来发展。送给每一个前端人,我们的征途是星辰大海

web APP

就是我们常说的 h5 应用,这个阶段属于满足展示功能阶段,首先是解决手机端能展示页面的问题。

实现方式就是客户端提供 webView 组件,就是一个基于 webkit 引擎、展现 web 页面的控件。web APP 实际上就是客户端提供了一个浏览器的宿主环境,能在手机上显示对应的网页内容,但是各大手机厂商对于内核都会有所谓的“优化”,这些所谓的优化或者内核版本升级所带来的兼容性问题,也是让前端同学咬牙切齿。

客户端提供了类似浏览器的宿主环境,前端将自己的 HTML/CSS/JS 运行起来,就可以看到页面了。但是在 PC 端原来我们看到的页面放在手机上,展示和交互都不太合适。之所以我们要叫 h5 应用,是说我们在移动端上需要用到 HTML5/CSS3 的新功能,通过这些功能能在客户端的浏览器上做适配展示页面。

响应式的布局方式,新式的 meta 标签,媒体查询等功能让前端以前显示在 PC 端上的页面能展示在手机端。随着 PWA 的出现,现在手机端逐渐对 Service Worker 的支持(Safari 还在踌躇犹豫),web APP 又重新焕发了青春。

优点:

  • 基于 webView 的跨平台,调试方便(控制台调试)
  • 开发速度快,只要有浏览器就能打开,适合小版本的试错
  • 无需安装,不占内存,随时更新,维护成本低

缺点:

  • 打开白屏时间长,用户体验较差,交互功能受限。
  • 产品也受限于浏览器,并且留存低,适合拉新
  • 不采用 PWA 的方案就无法离线,没有网络就失去了活力,现在不用网络的 APP 情况已经很少了。重复打开重复加载

代表产品:

  • 所有可以使用手机浏览器打开的网页(不做兼容展示会有问题)
  • 微信公众号里纯文章

hybrid 应用

跨过了 web APP 的满足展示功能阶段,这个时候开始想有更多的功能满足交互需求,比如调起原生的摄像头(虽然 input 也可以实现),这个时候催生了 hybrid APP,也进入了丰富功能阶段。

前端 webView 的交互实现无法直接与摄像头的 API 进行交互,类似这样的功能是客户端的能力,webView 想要完成这样的功能,如果不能直接完成是不是可以通过调用客户端来完成这样的功能,但是前端和客户端是两种不同的语言及实现方式,如何进行通信?

想要通信完成通信,其实就是需要再前端与和客户端搭建一个沟通桥梁,就是现在常说的 js bridge。介绍击中常见的 js bridge 通信方式。

js bridge

js 调用 native:

  • 请求拦截
  • 弹窗拦截
  • 注入 js 方法

native 调用 js:

  • 直接执行 js 代码

请求拦截

webView 发送请求都会经过客户端的请求发送模块,客户端可以在请求发送出去之前做拦截,大家约定好一种 URI 的实现协议,如果符合实现协议的请求,就拦截下来进行约定协议解析,其他的就当做真正的请求发送出去。

首先约定一个简单的协议

eros://bmImage/camera?params={"imageNum":2,"allowCrop":true,"callbackId":"bmImage.camera1527235458519"}

eros            // 作为协议存在,用于做拦截的方式
bmImage/camera  // 用于约定是调用客户端的方法名,可以是想要调用相机上传两种图片的接口
params          // query 表示参数,其中有一个参数名叫 params 的参数是一个 json,是调用客户端的方法所需要的三个参数
复制代码

不管 js 如何封装,就是需要发送一个请求出去,最好前端能做统一封装通过 iframe 或者直接通过 ajax 发送请求。

客户端如何拦截

android 的拦截方式 shouldOverrideUrlLoading

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    // 根据协议判断是否需要拦截
    if (true){
      // 解析协议路径得知调用方法
      // 解析 query 得到参数
      // 通过反射的方式去调用对应的原生方法
      return true;
    }
    return super.shouldOverrideUrlLoading(view, url);
}
复制代码

iOS 的拦截方式(UIWebView) webView:shouldStartLoadWithRequest:navigationType:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    // 根据协议判断是否需要拦截
    if (true){
        // 解析协议路径得知调用方法
        // 解析 query 得到参数
        // 通过 AOP 的方式去调用去调用对应的原生方法
        return NO;
    }
    return YES;
}
复制代码

上述过程就完成了 js 向 native 的通信的一种方式,客户端完成了操作之后如何告知 js 后面会讲到。这种方式不好的地方在于只能支持异步的调用方式,网络 I/O 就决定了这种方式不支持同步。既然是 URI 的协议就会有长度限制,超长了请求就会被截断

更为严重的是无序性和有丢消息的可能,这也导致了这个方式非常不稳定,也是早期没有其他选择使用的方式。

弹窗拦截

js 调用弹窗时一般有 alert/confirm/prompt 三种弹窗,这三种弹窗对应客户端都会有方法实现,可以直接做拦截。

var actionInfo = {
    type: 'eros',
    action: 'bmImage/camera',
    params:{
        "imageNum":2,
        "allowCrop":true,
        "callbackId":"bmImage.camera1527235458519"
    }
}

prompt(JSON.stringify([actionInfo]))
复制代码

android 拦截 prompt

@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    // 解析传过来的字符串判断 type 类型是不是解析的方式
    if (true){
        // 解析协议路径得知调用方法
        // 解析 query 得到参数
        // 通过 AOP 的方式去调用去调用对应的原生方法
        // 如果是异步返回
        return true;
        // 如果是同步,待上面的程序执行完毕之后返回结果
        // return res
    }
    return super.onJsPrompt(view, url, message, defaultValue, result);
}
复制代码

iOS 拦截 prompt(使用 WKWebView)

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
    // 解析传过来的字符串判断 type 类型是不是解析的方式
    if (true){
        // 解析协议路径得知调用方法
        // 解析 query 得到参数
        // 通过 AOP 的方式去调用去调用对应的原生方法
        // 如果是异步返回
        NSInvocation *invocation = [执行方法]
        [invocation invoke];
        return invocation;
        // 如果是同步,待上面的程序执行完毕之后返回结果
        return nil
    }else{
        执行对应的弹窗
    }
}
复制代码

这种方式比请求拦截好的地方是可以支持同步调用了。但是 iOS 中有两种 UIWebView 和 WKWebView,前者在 webView 中屏蔽的弹窗的功能。后者虽然内存要比前者控制的好但是有很多兼容性的问题。

js 注入上下文

上面的使用方式还是比较曲折,发展到现在有了 JavaScriptCore,也是现在大部分混合应用解决方案核心,JavaScriptCore 没有 BOM 对象也没有 DOM 对象,甚至还缺失一些浏览器的方法,但是这块是 js 和 native 都能访问到的公共区域。在打开 webView 之后,往 js 的上下文中注入方法,供 js 进行调用。

iOS JavaScriptCore 注入(UIWebView)

// 获取 WebView 中 JS上下文
JSContext *context = [webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//注入 callNative 函数方法
context[@"callNative"] = ^( JSValue * params )
{
    // 解析参数找到对应的方法进行处理
    // 同步回调
    NSInvocation *invocation = [执行方法]
    [invocation invoke];
    return invocation;
    // 异步回调
    return nil
}
复制代码

js 调用方式

callNative({
    action: 'bmImage/camera',
    params:{
        "imageNum":2,
        "allowCrop":true,
        "callbackId":"bmImage.camera1527235458519"
    }
});
复制代码

android webView 注入

// 通过 addJavascriptInterface 将对象映射到 JS 对象
// android 对象
// js 的对象名
mWebView.addJavascriptInterface(new JavaScriptBridge(), "callNative");
复制代码

js 调用方式

callNative.bmImage.camera({
    "imageNum":2,
    "allowCrop":true,
    "callbackId":"bmImage.camera1527235458519"
})
复制代码

这种方式就更接近写代码的方式了,不管是调用方式、传递参数的方式还是同步异步回调都更好了。但是这种方式也有需要注意的地方,首先需要注意客户端注入的时机,在 loadUrl 之前注入是无效的,但是在 FinishLoad 之后注入可能 webView 已经调用了方法,此时会出现调用不到该方法,所以还需要其他的机制来保证这个问题。比如微信公众号的 wx.config 接口。

native 调用 js

前面已经讲了 js 调用 客户端,js 在向客户端发出调用指令之后,如果是同步方法,比如 获取当前客户端版本能立即得到结果,如果是异步调用,之前每次调用客户端的时候都传递了一个 callbackId,这个就是为客户端回调 js 做准备。

首先 js 会提供一个方法等待客户端调用

window.nativeCallbackMap = {};
const callJs = (data) => {
    var data = JSON.parse(data);
    var callback = window.nativeCallbackMap[data['callbackId']
    if(callback){
        callback.call(null, data['resData'])
    }
    delete window.nativeCallbackMap[data['callbackId']
}
复制代码

iOS 调用 js

NSString *resDataString = [self _serializeMessageData:data];
NSString* javascriptCommand = [NSString stringWithFormat:@"callJs('%@');", resDataString];
if ([[NSThread currentThread] isMainThread]) {
    [self.webView evaluateJavaScript:javascriptCommand completionHandler:nil];
} else {
    __strong typeof(self)strongSelf = self;
    dispatch_sync(dispatch_get_main_queue(), ^{
        [strongSelf.webView evaluateJavaScript:javascriptCommand completionHandler:nil];
    });
}
复制代码

android 调用 js

final int version = Build.VERSION.SDK_INT;
// 因为该方法在 Android 4.4 版本才可使用,所以使用时需进行版本判断
if (version < 18) {
    mWebView.loadUrl("javascript:callJs()");
} else {
    mWebView.evaluateJavascript("javascript:callJs()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            // js 的同步返回
        }
    });
}
复制代码

上述 js bridge 的实现大致就是现在大部分的客户端与 js 的通信方式,现在 webView 也丰富了自己的功能,有能力调用客户端提供的方法,完成所有客户端能做的功能,js bridge 设计完之后剩下的就是需求推动,根据所需的功能提供不同的方法供前端调用。

如果需要与原生页面间互相通信,应该约定一种 scheme,也可以理解成一种 URI 的实现,通过 js bridge 的接口调用客户端(此时还可以传一个回调到客户端,当客户端完成某个操作之后返回该页面执行回调,比如日期选择),客户端解析协议,打开对应的原生页面,完成对应的操作。scheme 还是手机浏览器会识别的一种协议,如果有对应的 APP 可以直接呼起 APP,但是当你打开客户端页面的参数太多时,你的 scheme 会变得超长,浏览器会将 URL 截断,这个时候还需要简单的短链服务转化

优点:

  • 首先具有所有 webView 所有的优点
  • 解决了单纯 webView 的交互功能受限,能调用原生接口完成需求

缺点

  • 也无法避免 webView 所带来的性能问题,打开白屏时间长,用户体验较差,等问题,也存在受限与浏览器,及重复打开需要重复加载等问题
  • 所有新需要客户端提供的功能都需要客户端发版
  • 随着业务发展客户端定义的接口必须向下兼容,这会带来很多冗余代码

代表产品:

  • 公众号使用到微信 sdk 的功能
  • AppCan、PhoneGap、cordova 等 hybrid 框架

小程序

在 hybrid 混合应用稳定之后,大家发现功能上已经能满足开发需求了,所以下个阶段应该追求体验和性能上的提升,就是 RN 的方案了,ReactNative 的方案已经逐渐被大家所熟知并逐步落到项目中,混合应用方案也是本文介绍的重点,后面会详述。

这里想先讲一讲小程序,因为在技术的演进上小程序才应该是下一小步的提升,并且小程序严格意义上来说并非 APP 的一种方案,更像是微信分发生态中的体验进化,在使用公众号这类 hybrid 的方案时,发现体验和交互上的一些问题,比如加载白屏时间,页面之间跳转的交互,页面内容的缓存等等。

由于小程序现在实现方案面向开发者也是一个黑盒,我也是一边了解一边猜小程序如何实现的,小程序的框架包含两部分:View 视图层和 APP service。前者用来渲染页面结构,后者用来做逻辑处理,接口调用。他们在两个进程里运行,有点类似在当前的页面里使用 web worker,关系如下图:

APP View

我们写的视图层和逻辑代码是分离的,WXML 和 WXSS 构图了视图层的代码,WXML 通过 wcc 工具转换成 VDOM,WXSS 通过 wxsc 转化 style 标签。底层通过 WAWebview.js 来提供底层的封装,每一个视图就会有一个 webView 来渲染,这也就提高了页面渲染性能的问题,多个视图页面时就会有多个 webView 进程,所以小程序对页面层级是有限制的,内存受限。视图层主要包括以下内容:

  • WeixinJSBridge 封装和上述的 hybrid 的 jsBridge 一样
  • 小程序提供的组件注册,一些能操作 DOM 的 API
  • 渲染的实现:VDOM、diff、render UI(在高人知道下了解到渲染出来的本质还是 webview,在原生端只支持 flex 布局,但是小程序里还支持 web 的布局,由此可以看出,这里一定是 webView 的渲染,并非原生)
  • 页面生命周期管理

APP Service

逻辑处理的代码全部加载到一个进程 APP service 中,和视图 webView 不同,所有的代码逻辑都会一次性全部加载到这个进程中,因为主要的瓶颈还是来自于渲染性能,并且所有的逻辑代码都加载到进程中保证视图切换的流程性,并且加上小程序有 2MB 大小的限制,在现在的网络环境下一次加载体验会更好。APP Service 包含以下内容:

  • WeixinJSBridge 封装和上述的 hybrid 的 jsBridge 一样
  • 所有小程序提供的 API 方法注入,全局方法注入
  • AMD 模块化实现

小程序的开发环境

小程序运行在开发环境中和线上环境是不同的,线上环境 iOS 和 android 都有真正的 webView 环境提供,在开发过程中小程序提供了一个 IDE,IDE 是基于 nwjs 实现的,钉钉客户端也是基于这个实现的。其实就是在 PC 端的客户端环境下尽可能提供原生能力,如果是移动端才会有的差异化能力就会 mock 掉。两边环境不同还体现在 APP Service 中,APP Service 主要是调用客户端底层,所以底层的不同也影响着这层的封装。

APP View 与 APP service 通信

当我们理解了前面的 hybrid 的通信原理,这里的通信就比较好理解了。小程序的 bridge 实现原理就和 hybrid 一样了。iOS 和 android 就不多说了。基于 nwjs 的客户端是通过 window.postMessage 实现的,使用 chrome 扩展的接口注入一个 contentScript.js,封装了 postMessage 方法。

// 发送消息通过 
window.postMessage(data, ‘*’);
// 接受消息通过
window.addEventListener(‘message’, messageHandler);
复制代码

小程序的推动主要来自微信平台的大流量,这就是所谓的微信流量红利,公众号已经承载了传播和拉新的低成本方式,但是体验一直被诟病,限制于 hybrid 的体验问题让追求体验的开发者逐渐无法忍受,此时小程序原生的组件,良好多页面切换,几乎没有白屏时间的等待,让大家又有了探索无限的可能。

优点:

  • 首先具有所有 hybrid 所有的优点
  • 无需安装,极速打开
  • 原生的组件有了体验上质的提升
  • 性能上也有了新的飞跃,白屏时间,页面切换也有了更好的体验(为了减少白屏时间,小程序采用预加载的方案,而分不清哪个会是逻辑里的下一个页面,所以小程序将所有 webView 全局预加载,这也是页面层级和包大小限制的主要原因)

缺点

  • 只能用于微信平台,如果有多端的用户需求,开发成本增加了
  • 组件还是较少,很多操作 DOM 的方式也会有所限制,完成需求受限
  • 为了性能的体验,包的大小受限,打开页面的层级受限

代表产品:

  • 各种客户端的小程序

快应用

快应用是对标微信小程序的一场阻截,几大手机厂商联合发布这个方案,一瞬间吸引了大家的眼球,越来越多端让前端追都追不过来(这么多技术确实让人很绝望,甚至前段时间大家去恶意灌水了很多大项目的 issue,但这也是前端蓬勃发展的表现,当这些前沿的技术落地在项目中甚至你只是完成一个 demo 的时候,你还是会有抑制不住的兴奋和成就感)

快应用对自我的介绍是基于手机硬件平台的新型应用形态,用的是新型应用形态,并非新技术,类似这样的实现有 PWA,只是 PWA 缺少了手机硬件平台的支持。

图片来源:快应用发布会PPT

快应用标准是由手机厂商组成的快应用联盟联合制定,快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台。底层的硬件平台提供底层 API 让开发者调用,原生渲染组件,hybrid bridge 通信,原理大致也与小程序实现类似,这里就不详细说明,下面是几张快应用发布会的 PPT 截图,如果理解了上面的原理,这个应该就是比较好理解了。

之所以说是小程序的一场阻截,小程序曾放话说,未来两年内,小程序将取代 80% 的 APP 市场,而手机厂商并不希望大量的 APP 被取代,所以催生了快应用的落地。但是建立在几大国内手机厂商硬件平台上的方案,就目前来看支持性,通用性,社交性上都是比不上小程序的。两者的前景不敢妄加揣测,但是小程序凭借微信平台的用户量和用户粘性,比几大手机厂商实现的标准化还是一目了然的。

优缺点就不详述了,一目了然

Flutter

ReactNative 的开疆扩土进一步奠定了,React 的霸主地位,React 也由一个框架演进成了,以 React 为基础的前端多端解决方案,技术栈的生态方案。google 怎么可能放弃自己在科技领域的地位,即使是前端相关的技术,所以出了 Flutter 技术方案完成 APP 的一环。

借由本身的 android 和 chrome 的 平台优势,准备重磅推出 Fuchsia OS,打造自己不基于 Linux 的底层系统,而 Fuchsia OS 钦定 UI Toolkit 就是 Flutter。Flutter 最大的改进就是自己重做了渲染引擎去渲染页面,将混合应用的渲染性能推向了另一个高度。

Flutter 之于 RN 来讲最大的区别在于渲染,脱离了 JSFramework 的 Component 递归传递和逐个计算绘制,更像是 canvas 绘制,将 UI 直接绘制出来,Flutter 都是在状态变更时重新构建 Widget Tree,Flutter 的渲染引擎在将 Widget Tree 转化成渲染的 Render Tree,最后交给操作系统调用 GPU 去渲染,Flutter 由 Dart 程序写的,Dart 和 native 之间仍然存在一个接口,可以进行数据编码和解码,这可能比 JavaScript bridge 快好几个数量级。

使用 Dart 是整个框架不太被前端所接受的问题,但是代码都是相通的,上手还是很快,尝试 demo 期间还是很快就能模仿出一个页面,语言上的争论就不说了,毕竟都不如 PHP。

由于自己使用 Flutter 还在 demo 阶段,并没有真正围绕 Flutter 做过相关的解决方案,具体的细节实现也没有清楚的认知,也不适合展开详述,很早之前以矢量图起家的 Adobe 也尝试过类似的方案,但是最终没有把这条路走下去。

如果有兴趣可以移步:

weex 和 ReactNative

在讲这两种混合应用之前,再啰嗦几句,上面大致了解了各种混合应用的方案,这些方案了解其原理和使用场景,在合适的场景去使用对应的方案,不要为了落地某项方案而把业务生搬硬套,没有一种方案是绝对的好,在不同的业务需求的驱动下权衡利弊再做决策。

这两者一直有人在试图去比较分析得出利弊,看哪种更好,甚至有人偏激的认为 Weex 就不配合 RN 相提并论,但是我还是想说理性的看待这个问题,客观的面对前端技术,曾经 React 和 Vue 也是这样的差距,直到现在依旧有人认为使用 Vue 低俗,使用 React 高雅,但雅俗之分真的如此吗?还是应该理解其原理,辨别自己的业务场景,团队学习成本,开发体验等等一系列的原因,然后再做评判。

就目前的各方面情况讲,RN 确实更优,横空出世,背靠当时火的不行 React,一路都是风光无限。这种解决方案出来之后,如果没有竞争者的挑战,没有对比,没有选择,也不一定是好事儿,虽然现在两者还有很大的差距。

我猜 Weex 始于 KPI,毕竟大厂造轮子来升级是非常好的途径之一,但是往后发展,却成了两大阵营完善生态的方案,现在基于 React 的一整套的前端解决方案覆盖PC、Web、Native 可谓是成了大公司前端方案的标准套路,后起之秀 Vue 用良好的开发体验和低门槛的入门方式开始抢占用户,各种前端培训学校让一些前端不懂 js 基础,但是 Vue 溜的飞起。但Vue 并没有形成对 Native 的覆盖,这个可能也是 Weex 和 Vue 一拍即合的原因,双方都有需求,就开始了合作。

扯会正题,在大前端逐渐融合的背景下,作为以 Vue 建立技术栈的团队开始寻找客户端的方案,做技术选型开始考虑业务达成、团队学习成本、开发效率,性能效率等问题,我们一开始也是将 Weex 和 RN 作为比较,在上一家公司使用的是 RN,但是现团队建立技术栈基于 Vue,考虑到第二个因素偏向 Weex,实际调研过程中发现 Weex 的坑确实很多,但是好在有很多问题已经有解决方案了,当然不管想要使用上述两种方案,都需要有一定的原生能力。实际开发过程中发现随着对 Weex 的了解越来越多,开发效率也越来越快,入坑之后才发现了第三个和第四个甚至第五第六个优势。

至于 Weex 最大的卖点,兼容三端,Web 端这个优势每个人都有自己的看法,我们尝试了去兼容 Web 但是发现反而牺牲了开发效率,有兼容的时间,单独开发一套也出来了,并且更重要的是由于用户习惯的不一致,Web 端和 Native 针对的用户群体也不一样,在这个流量就是金子的环境下牺牲用户体验和开发效率去兼容 Web 并非是我们的初衷。

当然也遇到了一些问题,一开始 Weex 没有托管 Apache 的时候还有 issue,很多问题确实不能及时得到解决,所以决定脱离 Weex 的所有 module,自行开发所有 module,重新设计,这也让我们对项目有了一些控制。

决定了自行开发 module 和组件之后,减少了对 Weex 本身的依赖,项目本身受到的限制也越来越小,业务很快也完成了。当然现在类似 demo 跑不起来,毁灭式的升级,市场组件无法接入,bug 横飞,组件不足以完成业务功能,兼容性不足,热更新,公共文件导致包过大,社区经营不好等等这些问题,也都是一个技术产品成长的必经之路。

两种方案在选型的时候,一定有可取的地方才会选择,工程师的精神就是趟坑,找准正确的方向然后一往无前,两种方案都有已经上线的优秀产品,说明是这条路至少是能走通的,当然我们也在过程中总结了我们的解决方案,希望能帮助在 Weex 路上举步维艰的同行人,不管选择哪种方案,选择了就把他做好。Eros项目地址请戳(不要吝啬你的 star)Eros文档地址请戳。我们公司已有三个项目通过 Eros 上线,也有几十个应用通过 Eros 发布上线。

当然还有很多优秀的方案没有一一枚举,比如:kotlin、WebAssembly,每个方案都沉淀了很多前端工程师的积累,提供了各种能落地可实行的方案 phonegap -> cordova、mui、appcan、apicloud 等等



原文发布时间为:2018年06月08日
原文作者:还是怕麻烦
本文来源掘金如需转载请联系原作者

相关文章
|
7月前
|
前端开发 Android开发 开发者
移动应用开发的未来之路:跨平台框架与原生系统的融合
【5月更文挑战第30天】 随着移动互联网的蓬勃发展,移动应用已成为日常生活不可或缺的一部分。本文深入探讨了移动应用开发领域的最新趋势,特别是跨平台开发框架与原生操作系统之间的融合现象。通过分析当前市场上流行的跨平台工具如React Native、Flutter以及原生系统iOS和Android的最新发展动态,文章揭示了开发者如何在快速迭代的市场环境中选择恰当的技术栈,并预测了未来可能的技术融合模式。
|
4月前
|
开发框架 人工智能 前端开发
探索移动应用开发的未来之路:跨平台框架与原生系统的融合
本文旨在探讨移动应用开发的新趋势,特别是跨平台框架和原生操作系统之间的相互作用。我们将深入分析Flutter、React Native等流行框架的设计理念,以及它们如何适应不断变化的移动生态系统。文章还将讨论这些技术对开发人员工作流程的影响,并预测未来可能的发展方向。通过具体案例,我们展示了跨平台解决方案在实际应用中的优势和挑战,为读者提供对当前和未来移动应用开发趋势的深刻见解。
|
4月前
|
前端开发 Android开发 开发者
移动应用开发的未来:跨平台框架与原生开发的较量
在数字时代的浪潮中,移动应用已成为我们日常生活不可或缺的一部分。随着技术的进步和用户需求的多样化,开发者面临着选择何种开发模式以满足市场的挑战。本文将深入探讨移动应用开发领域中的两大阵营——跨平台框架与原生开发,通过比较它们的优势与局限,揭示未来移动应用开发的趋势和挑战。
89 1
|
4月前
|
开发框架 Android开发 开发者
融合风暴:跨平台与原生系统的超级进化,移动应用开发的未来之路即将改写
【8月更文挑战第7天】移动应用开发的未来之路:跨平台与原生系统的融合
40 1
|
5月前
|
机器学习/深度学习 前端开发 开发者
探索移动应用开发的未来:跨平台框架与原生开发的较量
【7月更文挑战第26天】随着智能手机和平板电脑的普及,移动应用开发已经成为软件开发中增长最快的领域之一。本文将深入探讨移动应用开发的现状与未来趋势,重点对比分析跨平台框架与原生开发的优劣,以及它们如何影响开发者的选择和最终用户体验。通过案例研究和技术演进的分析,我们将揭示在快速变化的移动市场中保持竞争力的关键策略。
56 2
|
4月前
|
移动开发 小程序 前端开发
跨端技术演进问题之Web容器方案在跨端开发中的优势和不足如何解决
跨端技术演进问题之Web容器方案在跨端开发中的优势和不足如何解决
|
5月前
|
开发框架 Dart 前端开发
移动应用开发的未来:跨平台框架与原生系统之争
【5月更文挑战第72天】本文深入探讨了移动应用开发领域的最新趋势,重点关注跨平台开发框架与原生操作系统之间的竞争。文章首先概述了移动应用的重要性及其在现代社会中不断增长的需求。随后,分析了当前流行的跨平台工具如React Native和Flutter,以及它们如何使得开发者能够用单一代码库为不同操作系统构建应用程序。此外,文中还讨论了这些工具与苹果iOS和谷歌Android等原生系统之间的比较,以及它们在性能、用户体验和市场接受度方面的差异。最后,文章预测了未来移动应用开发可能的发展方向,并提出了对开发者和企业的具体建议。
|
5月前
|
传感器 前端开发 物联网
跨端技术问题之为什么需要跨端技术
跨端技术问题之为什么需要跨端技术
|
7月前
|
机器学习/深度学习 Android开发 开发者
移动应用开发的未来趋势:跨平台与原生之争
【5月更文挑战第5天】随着移动设备的普及,移动应用开发已成为技术创新的前沿阵地。本文将探讨移动应用开发的两大主流模式——跨平台与原生开发,分析各自的优势与局限,并预测未来发展趋势。文章还将深入讨论移动操作系统的演进如何影响开发策略,以及开发者如何在快速变化的市场中保持竞争力。
106 13
|
7月前
|
移动开发 前端开发 数据安全/隐私保护
移动应用开发的未来之路:跨平台与原生系统的融合
【5月更文挑战第17天】 随着智能手机的普及和移动计算技术的飞速发展,移动应用已成为日常生活不可或缺的组成部分。本文深入探讨了移动应用开发的两大趋势——跨平台技术与原生系统应用的演进,并分析了它们如何塑造未来移动应用开发的格局。文章首先概述了当前移动应用开发面临的挑战,然后详细阐述了跨平台框架的优势以及原生系统应用不可替代的特点,最后提出一种融合两者优势的开发模式,旨在为开发者提供一个更加高效、灵活的开发环境。