crossplatform desktop/android/browser/nodejs architecture sketch
-
Hi All,
I made a sketch for a crossplatform architecture where the frontend is qml and the backend is c++ and would be interested in your opinions as I though do like qt, I'm not (yet) an expert.
The idea is to have the same qml ui on all platforms which communicates with the backend according to the command design pattern. Practically, these are the scenarios for each platform:
-
native (desktop): has normal qml ui which if necessary (say on click of a button), passes a command object (stringified json object) to an exposed method which passes it on to the backend. The backend here is a library that exports a function that receives the command and returns the response. The library itself implements the rest of the command design pattern. The response is returned to the ui by invoking a qml method.
-
Android: has a webassembly build of the same qml ui in a webview that passes the command json object via webmessage channel through the webview to the android java layer which passes it on to the c++ backend library via java native interface. The backend is the same c++ library but crosscompiled for android. The response is returned to the qml ui via webmessage channel.
In this case only an android wrapper app is necessary that handles a webview for the ui and handles the "backend" calls. Theoretically, the same can be done on iOS as safari has the webmessage channel concept as well but I'm not familiar with that platform at all. -
browser: I have not tried this yet but this I expect to be a simple webassembly build of the native version.
-
nodejs: has a webassembly build of the same qml ui which is loaded on a GET request from the nodejs server. When necessary, the qml ui posts a command json object in a request to the appropriate endpoint of the nodejs server where the request is handled and the command json object is passed on to either a webassembly build of the backend library or a nodejs N-API C++ addon that wraps the backend logic. The response is then returned to the client from nodejs and then to the qml ui either via the webassembly built qml method invocation or via emscripten inline javascript.
I implemented the first two and uploaded to a repo with all build artifacts (including the android apk) which you can find here:
This is currently just a sketch and there's no real command json object sent (and no command design pattern in place) when you click on the text "Hello world" but some test strings are sent like "Hello from QML" to backend and the response is "Returned from backend: Hello from QML".
All builds are debug builds without any optimization so the android app load time is damn slow but afterwards it works just like the native one. As mentioned, I'm not a qt expert so you need to comment/uncomment this and that in the project file configuration (especially for the ui which is in the qmlwasm1 directory) to get a successful webassembly or native build.
The main parts of the repo are:
qmlwasm1: contains the qml ui logic (depends on qwa_pure_backend when compiled for native)
qwa_pure_backend: contains the backend logic
Android/qmlwasm1: contains a full integration of the ui and backend in an android appRecommendations are welcome :)
Best regards,
r0ller -
-
Added the nodejs scenario (4th above) today if anyone is interested :) The relevant directory is:
qwa_node
As I built the webassembly qml ui for that last time and the build artifacts were pushed to the repo as well, issuing
node index.js
in that directory shall fit the bill to try it out ;)
I also simplified the builds via the project file to 3 defines:
__ANDROID__
__NODEJS__
__NATIVE__So only one of those need to be uncommented for the relevant target. (There's a todo for this to define them automatically based on the target but I don't yet know how to do that.) Building the qwa_pure_backend for it was not smooth as the project file settings did not make it to the effective qmake call so there's a manual_build.sh in the build-qwa_pure_backend-Debug directory.
I don't know when I'll have time for the 3rd scenario but that's relatively simple to build and I don't have many use cases for standalone webapps anyway.