Serving QML applications over the network

Download Serving QML applications over the network

Post on 26-Jun-2015

3.673 views

Category:

Technology

3 download

Embed Size (px)

DESCRIPTION

Qt Quick's support for network transparency makes it possible to serve an application's user interface and logic over the network. This allows application developers to adopt fast web-like release cycles, but it does require some planning ahead. The presentation will highlight some benefits of serving QML applications over the network, give an overview of QML's network transparency support and illustrate how to build and serve QML applications. The presentation will also address some of the challenges encountered in a real world application deployment.

TRANSCRIPT

  • 1. Serving QML applications over the networkJeremy Lain Wifirst

2. Jeremy Lain Using Qt since 2001 (desktop, mobile, embedded) Occasional Qt contributor (QDnsLookup) Head of software development at Wifirst (ISP) Lead developer of a IM / VoIP app for Wifirst customers 2 / 35 3. Overview 1. Why serve applications over the network? 2. QML network transparency 3. Building your application 4. Deploying your application3 / 35 4. 1. Why serve applications over the network?4 5. Typical application deployment Development Packaging In-house beta testing Push application to all users Repeat!Each iteration requires per-Each iteration requires per-platform installers and an update.platform installers and an update. 6. Options for handling updates Manual updates Most users cannot be bothered to update You end up with a heterogeneous installed base Your cool new features dont reach your users! Automatic updates Not all platforms have an application store Each platform requires specific packaging wok Usually requires elevated permissions (Windows UAC..) 6 / 35 7. Updates are hard! Not convinced? Look at the Chrome Not convinced? Look at the Chrome and Firefox codebases! and Firefox codebases! 7 / 35 8. How about QML apps? C++ wrapper code: has usual deployment constraints QML / Javascript code and resources: fully cross-platform conveniently split into multiple files can be loaded over the network by QtQuick 8 / 35 9. Some benefits Faster iteration and testing Fix bugs after release! Progressive update roll-out Split testing for UI changes Time-limited changes (Christmas specials!) 9 / 35 10. 2. QML network transparency10 11. Loading QML from C++QDeclarativeView (Qt4) and QQuickView (Qt5)support loading from an HTTP URLint main(int argc, char *argv[]){QApplication app(argc, argv);QQuickView view;view.setSource(QUrl(http://foo.com/main.qml));view.show();return app.exec();}11 / 35 12. QML loader elements Built-in QML elements with a source property support HTTP URLs Image Loader FontLoaderImage {source: http://foo.com/bar.img}12 / 35 13. Relative URLs Relative URLs are resolved relative to the QML documents URL Image { source: head.jpg } file:///home/bob/foo.qml file:///home/bob/head.jpg Image { source: head.jpg } http://example.com/foo.qmlhttp://example.com/head.jpg You can use the same code locally and remotely! You can use the same code locally and remotely!13 / 35 14. QML network transparency QML type declarations can be served over HTTP, but you need to list your types in a qmldir file: Button 1.0 Button.qml CheckBox 1.0 CheckBox.qml Javascript code can be served over HTTPimport scripts/utils.js as Utils 14 / 35 15. Translations Loading translations from QML is missing You can provide your own TranslationLoader and doTranslationLoader { source: i18n/my_translation.qm onStatusChanged: {Console.log(status is: + status); }} A proposal for including it in Qt5 https://codereview.qt-project.org/#change,3186415 / 35 16. 3. Building your application 16 17. General recommendations Split models and presentation The C++ code still needs traditional updates Make the loader robust Keep the API simple Keep the API stable Serve all the rest on the fly QML and Javascript code Resources (images, fonts, translations) 17 / 35 18. Application architecture fontawesome.ttfbackground.pngRemote content Button.qml main.qmlLocal C++ code ApplicationPlugins18 / 35 19. The application Creates the QML view Sets up the QNetworkAccessManager Loads a single root QML file over the network Can fallback to local files for offline use 19 / 35 20. Application / setting up QNAM Give your application a User-Agent Helps track usage, or serve different content QtWebkit generated request already have a UA Specify the preferred language (Accept-Language) Set up a persistent network cache Configure HTTP pipelining 20 / 35 21. Application / caching QtQuick caches components + pixmaps (memory) QNAM supports If-Modified-Since but needs a persistent disk cacheclass MyFactory : public QQmlNetworkAccessManagerFactory{public:QNetworkAccessManager* create(QObject* parent){QNetworkAccessManager* manager = new QNetworkAccessManager(parent);QNetworkDiskCache* cache = new QNetworkDiskCache(manager);cache->setCacheDirectory(/some/directory/);manager->setCache(cache);return manager;}};view->engine()->setNetworkAccessManagerFactory(new MyFactory());21 / 35 22. Application / HTTP pipelining Splitting QML into files: good but incurs overhead HTTP/1.1 allows sending multiple requests without waiting for replies Particularly useful for high latency links Qt5 uses pipelining for all resources Qt4 only uses pipelining for pixmaps and fonts subclass QNetworkAccessManager if needed 22 / 35 23. Application / offline useAt startup, fall back to a bundled copy of yourQML code if loading from network failsvoid MyView::onStatusChanged(QQuickView::Status status){ if (status == QQuickView::Error && useNetwork) {useNetwork = false;setSource(QUrl(qrc://main.qml)); }}Catching errors later is harder..23 / 35 24. Plugins Define data models and scriptable objects Keep the C++ code simple : if something can be done in QML instead, do it! Keep the API stable : if you change it, you will probably need different QML files 24 / 35 25. QML content Welcome to an asynchronous world!var component = Qt.createComponent(source);var object = component.createObject(parent); BAD var component = Qt.createComponent(source); if (component.status == Component.Loading)component.statusChanged.connect(finishCreation); elsefinishCreation(); GOOD function finishCreation() {if (component.status == Component.Ready) { var object = component.createObject(parent);} }25 / 35 26. QML content Review your timing assumptions! Do not depend on objects loading in a set order Use Component.onCompleted with care Having lots of icons can be a problem, consider using web fonts like FontAwesome 26 / 35 27. 4. Deploying your application27 28. Hosting the QML code You have all the usual web hosting options Run your own servers (nginx, apache, ..) Use cloud services Do load-balancing, fail-over, etc.. QML files can be 100% static files, or even generated on the fly 28 / 35 29. Version your root URL Plan for multiple versions of your C++ app, as the API will probably change, e.g. : http://example.com/myapp/1.0/main.qml http://example.com/myapp/1.1/main.qml Alternatively, switch on User-Agent 29 / 35 30. Cache consistency Consider two related files Dialog.qml and Button.qml, which must be in the same version to work Caching can cause inconsistency App start 1 User click 1App start 2 User click 2 Button.qml Button.qmlversion 1version 1 FAIL!Dialog.qml Dialog.qmlversion 1version 2time 30 / 35 31. Cache consistency Your main.qml can load all subsequent contents from a subdirectory to version the QML code Layout: main.qml RELEASE_ID/Button.qml RELEASE_ID/Dialog.qml 31 / 35 32. Security Make use of HTTPS to avoid your application loading malicious code (DNS hijacking) Make sure your certificates are valid! Some platforms or custom certificates will require adding your CA certificates QSslSocket::addDefaultCaCertificates(./myca.pem);32 / 35 33. Performance considerations Enable gzip compression for QML and JS files Set an Expires header to avoid QNAM re-checking all files on startups Serve from a cookie-less domain 33 / 35 34. 5. Questions 34 35. Get the code Source code for the Wifirst IM / VoIP client git clone git://git.wifirst.net/wilink.git 35 / 35