Cordova hybrid apps - How to structure your codebase

February 23, 2019

The problem

A cordova hybrid app necessitates changing the generated native project, thereby breaking the ability to use cordova cli features like adding plugins, updating cordova etc.

Some definitions

Cordova

Cordova let’s you build cross platform mobile apps, while designing the UI using web technologies (html/js/css). The app runs in a native WebView which is basically a browser. The inner cordova browser allows access to native device capabilities through cordova plugins. These have a js side and a native side (java/kotlin/swift/objective-c/whatever).

Cordova CLI

CLI tools that generate native platform projects from your web app. They add the cordova platform logic, and are used to add plugins, update the platform, generate packaged app store installations etc.

Normal cordova app

The usual way of loading the app’s UI is locally with file:/// protocol. So you build a static website, deploy it to the device, and the WebView loads the website from the local device’s folder. Accessing the server is done via ajax/sockets.

local

Hybrid cordova app

But wait, if cordova gives us a browser, and we’ve already built a responsive website, why not load that website inside our cross platform app? This approach is called hybrid, and often involves some extra layer of native UI like a menu or settings screens apart from the main WebView.

Notice that loading remote content isn’t officially supported by cordova, but in some cases it’s ok. More about this in my next post.

remote

In order to add your own UI layer like a menu or settings screen to your hybrid app, you need to take the generated platform project, let’s say android, and add stuff to it. But there’s the rub, because the cordova cli tools will override those changes next time you build the platform. Directly editing the generated platform files is discouraged for this reason.

If you start changing the generated project, you no longer use cordova cli to:

  • add plugins. manually adding plugins is a headache.
  • get new versions of the cordova platform
  • get security updates

A suggested architecture

My current way of designing the code base structure is the following:

  • Generate a native project with cordova platform add

    • This generates the project under /platforms/<platform-name>
    • Everything under /platforms is ignored by source control.
  • Copy the generated native project to <platform>-project (android-project or ios-project)

    • Make your native changes in that folder.
    • This folder will be source controlled.
  • Write a task for generating the platform project and updating your native project

edit

The “generate” task

You can use some task runner like gulp or grunt (I use grunt) to keep the project in sync. The task will (to take an android platform for example):

  • Copy your modified files from android-project to temp
  • Build the platform with cordova build android
  • Copy /platforms/android to android-project
  • Copy and replace from temp to android-project

This way you always have a working Android Studio project in the android-project folder, which is source controlled, but still have the ability to update cordova and add plugins using the cordova cli.

Comparison with embedded WebView approach

In the cordova website they describe an approach to embedding WebViews which is to basically create a project and add a cordova WebView manually. I like the approach described here better for several reasons:

  • You don’t have to create a project from scratch, integrate cordova jar files manually etc.
  • You get to use cordova cli’s scaffolding and folder structure, which is subject to change/update.
  • Easy plugin installation/removal with cordova cli.
  • Easy cordova platform updates.

Next steps

In future posts I’ll show the creation of a sample project actually implementing all this, stay tuned :)


Written by@Jonathan Perry
Fullstack dev - I like making products fast

GitHubMediumTwitter