Building hybrid apps; is it even possible?

My friend and I have been building a fairly simple mobile app with Meteor for about a month now. We used Meteoric and Bootstrap, and nothing hacky. We hit some major performance issues in the middle, but could solve it by integrating with WKWebview. However, we were really disappointed when we first ran our app on Android, because it was just too slow to use. We then learned about Crosswalk, and finally got to use it after today’s release (THANK YOU METEOR TEAM!!). But we feel like we’ve hit another major block, and we are not sure how to recover from it. I posted two videos of running our app both on iOS and Android. Adding Crosswalk definitely helped performance, but you will notice the jittering motion between transitions, and whenever keyboard shows up. I’ve seen that there are other production services built in Meteor but now I am a little suspicious that maybe there haven’t any production mobile apps built in Meteor. Could anyone here provide some insight? We are actually thinking of giving up on this hybrid approach and learning how to build native apps…

  1. Running on iOS: http://youtu.be/dxfhS0C6hpo
  2. Running on Android: https://youtu.be/u0ebeev2fcE
1 Like

I’m not sure what is going on in your specific situation. I don’t think the jittering is a performance issue though, it seems more like the transitions need some fine tuning. For instance, it seems the transition at 0:20-0:21 on Android does a fade to black which causes some flickering. Maybe other people have better suggestions.

In general, transitions are one of the most difficult parts to get right using web technologies, because you’re basically trying to replicate native behavior that has been refined over many generations. The details of the transitions are often surprisingly complex, and as a user you’ve become unconsciously attuned to these details. If it’s not exactly right, it just feels ‘off’.

True hybrid apps, which allow you to combine native views and behaviors with web content, are an interesting direction for the future I think. But that’s not to say you can’t be successful with pure web technologies, just that it might be a little more work to get things right.

There may be other solutions you can use right now. I haven’t used this myself, but I know of one app that uses this plugin to combine native transitions with web content:

1 Like

@martijnwalraven thank you so much… After a few other attempts, we decided to move onto a “native wrapper” approach; use native source code to do navigation and wrap meteor app inside a webView. This is working pretty well so far except that I have to invoke window.location = someUrl every time I do routing because inside iOS, I detect whether the user has navigated away from the currentView like following:

    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        performSegueWithIdentifier("GoToPostsShow", sender: self)
    }

The problem with this is that since I make a fresh request for every navigation, the app performance suffers. I am looking for a better solution for iOS to detect in-app navigation without having to set window.location everytime.

This is what I did for iOS so far:

  1. Create a ViewController for each page (ex: /posts/id, /posts, /users, etc.)
  2. Use the native NavigationController to move around the pages
  • this requires that I must do a full render of a page for every navigation, giving up Meteor’s partial rendering. In other words, I have to make Meteor not single page app anymore because I must use UIWebVIew’s shouldStartLoadWithRequest.

Result:
Transitions are very smooth between pages, but each page needs loading time that would’ve been avoided in a regular Meteor app. Although each page needs to be loaded again, the native transitions make the app look more native than the app built with Cordova and Meteor-ionic. Trying to imitate the native transitions in javaScript seems to be not good enough.

Question:
Can you think of any other way than what I am doing to achieve a performant mobile hybrid app? I did some more research and there seem to be many hybrid apps that are used in production. I am not sure where they get the necessary performance boost…

1 Like

Other people may be able to tell you more about improving performance / user experience without using native views and transitions.

You’re right, reloading each page in a new web view has some serious drawbacks. It is actually worse with Meteor because it also means that each web view will have to open a new DDP connection and reload all data.

I can think of various ways of working around this. One trick would be to share the same web view between view controllers. For instance, you could take a screen shot of the web view before a transition, replace the web view in the source view controller with an image view, and pass the web view to the target view controller. The plugin I linked to above does something similar I believe, but it doesn’t work with a navigation controller.

Maybe take a look at React Native as well!

These guys seem to have found a very solid approach to hybrid mobile performance:
https://hansoftx.com/blog/building-an-ultra-responsive-ui

I haven’t tested anything of this, but looking forward to do so.
Maybe it helps.

I really wanted to try React Native, but the problem is Android isn’t supported yet. :frowning:

1 Like

Taking a look at it right now!!

have you used nativescript… its awesome

One thing to add here is that iOS app usually build pretty well especially with WKWebview, but Android always seems to be the problem.

Is sharing the same UIWebView possible? (http://stackoverflow.com/questions/32341819/using-the-same-uiwebview-across-different-viewcontrollers)

Yes, you should be able to move the UIWebView from one view controller to the other. Just make sure you add the right constraints or set an autoresizing mask when you add it as a subview.

1 Like

I’d appreciate it a lot if you could take a look at this when you have 10 minutes to spare. For some reason, re-using a previously loaded UIWebView doesn’t seem as simple as it sounds…

What do you want me to take a look at? I think you probably meant to link somewhere?

Oh, yes I meant to link to this question. Thank you so much for sparing your time for me by the way. I really appreciate it. – never mind!! I solved it. I don’t think screen capturing is necessary if you use the events before transitions carefully. I will let you know when things are finalized!

Good to hear! Looking forward to hearing about your experiences. I suspect you might encounter a need for taking a screen shot before the transition after all, if you want to support things like the interactive pop gesture for example.

Making these types of hybrid apps easier to develop is definitely something on my mind. I hope to find the time to do some work on this in the future.

Hey @martijnwalraven this is the current status!

  1. on Simulator: https://youtu.be/OGR-gvSzeQw
  2. on iPhone6: https://youtu.be/A7EY0K0Nng0

You will notice on a simulator, the app is perfect. Users would believe it’s a native app. However, on a device, there’s unwanted 100ms delay between transitions. This is the last block that I must solve, and I thought you would have insight on this one too!

I followed your advice of doing transitions. I recycle a webView and in between transitions I execute either Router.go() through javascript or webView goBack() natively. In the above case, where you navigate from a detailedView to indexView, I do

- (void)willMoveToParentViewController:(UIViewController *)parent{
    if (parent == nil){
        [_webViewManager.webView goBack];
    }
}

The issue might be resolved if I could invoke goBack a little faster. But I am not sure where the real cause for that extra 100ms lies.

If you look at those movies frame by frame, there are actually some problems both on the simulator and on the device, they are just more pronounced on the latter. The main difficulty is in coordinating the route change in the web view with the transition. In the ‘imperfect’ movie, on the first transition, you can see the web view changing to the new screen before the transition starts (although without the data loaded). The second transition completes first with the old screen and then suddenly switches to the new one.

Replacing the web view in the source view controller with a screen capture would help replacing the screen too soon. It would also improve the user experience of the transition. If you think about it, what makes a transition work is that you have both the source and target view visible at some point, and only displaying the shared web view will never allow that.

The second problem is more difficult to solve, because you need to make sure the original page is never shown in the target view controller. You could wait until the route change and resulting load have completed, but that would delay the start of the transition and that might not give a very nice user experience. Alternatively, you could start the transition without the web view in the target view controller, but with a progress spinner for instance. And you then replace it with the web view when the new page load has been completed.

I realize this is all getting quite complicated, and although I admire the experiment, I know from experience how much work this can be. You want to make sure you don’t get sidetracked too much and leave enough time to actually build your app! So depending on the type of app you might be better off with a slightly less nice web-based solution, especially if you also require Android support. I really hope supporting these more hybrid approaches can be made easier, but that might be a while.

1 Like

Thank you so much again. The app is actually built already but without these natural transitions the app doesn’t seem complete to the users. It is getting complicated but we don’t have a choice… What do you mean by slightly less nice web-based solution?

I don’t understand how Amazon and Instagram handle transitions so beautifully in their mobile apps…