So why would you want to make a web app work offline anyway? Mainly because there are lots of situations, where the network connection is not good or temporarily not available: e.g. when travelling, in bigger buildings (like warehouses), etc. Most Fiori apps are basically a remote control for some SAP backend functionality and loosing the connection in midstream sure can be quite frustrating for the user. So since most logic still happens on server side, we are actually talking about being part-time offline. Technically, there are three main problems to solve:
- The app must be able to start/restart offline: so we need all UI elements (javascript, images, etc.) to be accessible even without a connection to the server.
- Required data must be accessible offline (e.g. the current worklist).
- Changes in the data and action calls, that would normally be sent to the server right away, must be processed on the client and sent to the server later, once the connection is established again.
So, in a nutshell, we need to keep a copy the app structure and a subset of the data on the client and sync them with the server whenever possible. This is far from trivial as web browsers normally just render whatever a server gives them and do not store anything for longer use. Luckily, there are multiple ways to overcome these difficulties.
Overview
The following feature matrix shows all the possibilities in direct comparison. Scroll down or click on the table heading for a brief introduction to the selected approach.
Feature | SAP offline oData + Cordova | Neptune UXP | Progressive Web Apps | AppCache |
---|---|---|---|---|
Installation on device required | Yes | No | No | No |
Dedicated app icon | Yes | Yes | Yes | Yes |
App can be started offline | Yes | No | Yes | Yes |
Data subset can be kept offline | Yes (replication) | Yes (replication) | Yes (cache) | Yes (replication) |
Data can be altered offline and synced later | Yes (sync) | Yes (sync) | Yes (buffer or sync) | Yes (sync) |
Sync-tools for UI5 available out of the box | Yes | Yes | No | No |
Prerequisities | SAP Cloud Platform or SAP Mobile Platform |
Neptune UX Platform | - | - |
Works on Fiori Launchpad | No | No | Only online *** | Only online *** |
Works as BSP on NetWeaver | No | No | Yes | Yes |
Mobile support | Android, iOS |
Android, iOS, Windows |
Android, iOS**, Windows 10 |
Deprecated |
Desktop support | - |
Chrome, |
Chrome, Firefox, Safari** Edge |
Deprecated |
Background-sync | Yes | Yes (if app open in browser) | Yes | No |
Client-side storage limit * | Device free space (max. 2 TB) | 5-50 MB | 0,2-1% of device free space | 5 MB |
* The storage limit strongly depends on the browser and the operating system. The numbers provided are just typical values to give you an orientation.
** Safari currently (06.2018) only support basice PWA APIs - in particular, the Background Sync API is not yet supported.
*** A PWA can be run from the Fiori Launchpad but it will only work as a regular web app. As of july 2018 there is no way to register a ServiceWorker.
SAP offline oData
SAP itself promotes the idea of using native or hyrid apps on mobile devices if offline functionality is required. For our case, a good choice would be a hybrid app, which is a web app running inside a special container instead of a normal browser. The container is a native mobile app and provides access to device storage, hardware drivers, etc. Such a hybrid app behaves just like a native one except for the UI and logic being HTML and JavaScript and not something native to the platform. In particular, hybrid apps must be installed and updated just like regular ones.
SAP provides tools to create hybrid apps within their SAP Cloud Platform or the SAP Mobile Platform. Both use Apache Cordova as container and a set of SAP plugins called "Kapsel framework". Offline support is provided in the form of a middleware called "offline oData". This middleware reads a subset of the server data from a regular oData service and replicates it to connected mobile devices. The mobile app than work only with this data replica, which gets synced back to the middleware by a Kapsel-plugin. The middleware, in turn, will sync further to the original data source. However, the synchronization between app and middleware is not really automatic. SAP provides interfaces, but there is still a lot of coding to be done.
At the bottom line, a UI5 hybrid app can work totally offline once it received it's data subset initially: the JavaScript and all the assets are packaged within the Cordova container and the data is distributed and synced via offline oData.
The downside of this approach is being bound to SAP Cloud Platform or SAP Mobile Platform, which can get really expensive depending on your needs. Another problem is the device and version management: in contrast to regular Fiori apps, hybrid ones must get explicitly installed and updated on each device.
It is also important to understand, that such apps will allways work with their data replica (at least for the oData endpoint, that was made offline) - even if currently online. The decision, wether to use offline oData or not, must be made early in the development process as it has significant impact on the code. Additionally, every step in the synchronization may poduce errors or conflicts, which need to be dealt with somehow - see below.
Neptune UX Platform
The Neptune User Experience Platform is a third-party low-code platform for building and running SAP UI5 applications. At it's heart, it is a JavaScript code generator with a tree-based tabular UI and most coding done in ABAP. It also provides various tools along the entire lifecycle of an app. Neptune apps work with their own backend, which is integrated with SAP, but has a separate launchpad, etc.
Among other features, there is also a possibility to cache any data for offline use. The idea is similar to SAP's offline oData: you can choose to store a subset of your oData entities in a local database within the client (LocalStorage or WebSQL). This local data is automatically held up to date: All changes are made locally and synced back to the Neptune UX Platform and from there to the SAP backend.
Enabling offline support for a Neptune app is easy: it is just another setting for an oData service, where you can choose, which browser storage to use. There is also a JavaScript API for custom access to the offline data. In real world scenarios, the impact of offline support on the app code seems less, than with offline oData. It is also worth to mention, that Neptune apps will also work offline on desktop browsers.
However, Neptune does not provide a way to make the app structure be available offline, so your data will be fine offline, but the app itself will only work as long as you do not close or reload the page in the mobile browser. However, there is a possibility to use Neptune apps within Cordova hybrid apps as discussed above.
Another issue may be the storage limits of the provided client storage options: LocalStorage has a limit of 5 MB in most browsers and WebSQL provides up to 50 MB, but is poorly supported by browsers and even concidered depricated. Again, using Cordova hybrid apps helps overcome these difficulties.
Progressive Web Apps with UI5
Progressive Web Apps (PWA) leverage the latest browser technologies to provide a native-like experience - in particular, allowing web apps to launch and work entirely offline. The main idea is to cache server requests and serve them from the cache if needed. The so-called "Service Worker" is responsible for this caching within the browser. It allows to prefetch all HTML and JavaScript and also some data and make the app run offline without any explicit installation.
Current versions of SAP UI5 (starting with 1.52) support ServiceWorkers and the browser Cache API. The app developer needs to initialize a ServiceWorker and tell it, which resources to cache - see my UI5 PWA tutorial for details. While HTML and JavaScript can be almost automatically stored on the client using the Cache API, the data should be saved in the browser storage engine IndexedDB explicitly from within the application code.
The difference to offline oData and Neptune approaches is here, that the offline data is not neccessarily an exact replica of an oData collection on the server getting synced in the background. The developer is free to choose, wether the app allways works with the offline data or only uses it as a fallback if no connection available. It is even possible to choose different approaches for different requests. This is a lot more flexible, but also requires more carefull application design.
The main advantage of progressive web apps is the simple architecture on client and server side: no containers, no middleware, everything just like in the case of a regular web app. In other words, there is no need to install anything neither on the client nor on the server.
On the downside, there are no ready-made tools for SAP UI5 specifically, so you will need to code all the data synchronization from scratch. Additionally, not all browsers fully support PWA features. You can use my PWA checker to check you target browsers: just open it in the browser of every device you plan to use to see, which features it supports.
AppCache (cache manifest)
Many older UI5 tutorials suggest the use of HTML5 application cache also known as cache manifest. However, this technology is obsolete and is being gradually removed from browsers. In 2016 it had been fully replaced by the Service Worker (see above). In a nutshell, the AppCache allowed to tell the browser to cache certain resources for offline use by linking a special cache manifest in the HTML. That manifest file enumerated all resources to be cached and also those to ignore. This approach did not work well for larger apps with many files as it allowed only basic configuration.
Conflict and error handling
Note, that handling conflicts and server errors is much harder with deffered synchronization, than with immediate server interaction. For example, an object may get altered or even deleted on the server while it was being worked with offlie. There will be no errors when saving that object in offline-mode since the app does not (yet) know, what happened on the server. But the sync will fail in the background while the user is sure to have saved everything correctly. A similar problem arises, when complex plausibility checks are performed on business objects in the server: you don't want to duplicate all that logic in the client.
Neither of the offline approaches discussed here offers a ready-to-use solution for handling background errors. It is up to the developer to create some kind of error log or other visualization and to offer the user ways to deal with conflicts. It is important to keep this in mind, as it may have significant impact on the development costs.