How many times have you embarked on a journey only to be presented with the obstacles of intermittent connectivity? Offline-enabled functionality has long been a hot topic in the web development industry, but only recently have compelling solutions truly emerged that resolve many of the issues associated with building offline applications that provide for a variety of use cases. Luckily, with the support of Yjs, an open-source real-time collaboration framework, and new browser technologies like Service Workers and IndexedDB, a local database that functions offline, developers the world over can now take advantage of these approaches to architect offline applications of their own.
Not long ago, this author (Preston So, Editor in Chief at Tag1 and author of Decoupled Drupal in Practice) was privileged to host a Tag1 Team Talks episode about how Yjs enables offline applications in conjunction with my Tag1 colleagues Kevin Jahns (creator of Yjs and Real-Time Collaboration Systems Lead at Tag1), Fabian Franz (Senior Technical Architect and Performance Lead at Tag1), and Michael Meyers (Managing Director at Tag1). In this blog series, we take a look at how precisely developers can implement robust offline applications with Yjs and IndexedDB. In this second installment of the series, we extend our discussion of how to support offline applications and begin to dig into how Yjs is optimal for any offline use case involving collaboration.
How offline data acts as another cache
If you have not yet perused our first installment in this blog series about offline-enabled applications with Yjs, I highly recommend you do so, as the first blog post in our exploration of offline applications focuses on defining offline terminology and setting the stage for how IndexedDB and Service Workers enable architects to conceive compelling offline-enabled architectures for their own applications.
During our chat together, Fabian made the eloquent point that offline applications are particularly useful as another cache for the offline user. For instance, consider how we validate content when we realize that it is stale in the browser. Whenever a user approaches an offline database and requests data, that store emits the data that they have available. This often occurs in a content delivery network (CDN) such as Fastly, Varnish, or CloudFlare.
In the offline application case, while you are fetching data from the offline database, a Service Worker running in the background checks with the server to verify if a new version of the content on the site is available. When there is an updated iteration of the data available, the new version is provided by the database and stored in the cache represented by a user’s local IndexedDB database. This enables users to automatically have the fetched version of the cache no matter what.
Of course, from the caching perspective there is always a timeout; we don’t wish to serve users who are in the process of synchronizing any content that is more than a day old. The new cached version of content could be ten seconds faster than another user’s; as such, every user will be able to benefit from a fast cached experience while Service Workers are in the background reproducing and recreating the website. Indeed, one of the most compelling aspects of Service Workers are that they can be leveraged as an additional content delivery network (CDN), and as a matter of fact, CloudFlare supports Service Workers natively on their own CDN platform.
What is IndexedDB?
Of all the technologies involved in building offline-enabled applications for the web, perhaps none is as essential to the functioning of your implementation as IndexedDB, which provides local object storage. Historically speaking, IndexedDB is an evolved rendition of LevelDB, a database technology developed by Google that is embeddable in any application. The key difference between LevelDB and IndexedDB is that IndexedDB is embedded directly in your browser.
When implementing offline applications, it is crucial to remember that each website has access to a single IndexedDB database. This database has limited query functionality and is not quite as powerful as SQL, the most common database language, but it performs extremely efficiently. Nonetheless, IndexedDB’s functionality is what distinguishes it for offline-enabled applications.
To illustrate this, consider the fact that Service Workers utilize IndexedDB in the background to store a full copy of the website for offline accessibility. As such, an IndexedDB database has context to store resources or any other information necessary to retain whiel offline. Service Workers can access this database arbitrary in order to retrieve other content and serve said content to the client as needed.
Encryption in IndexedDB
During our recent Tag1 Team Talks episode about WebRTC and building peer-to-peer collaborative applications with y-webrtc, we spoke about the fact that leveraging Yjs and y-webrtc enables end-to-end encryption. In the course of our webinar together, Michael asked a key question on the mind of any security-focused developer when it comes to enabling offline functionality: How precisely does IndexedDB handle the need for encryption? With IndexedDB, is information on other sites accessible, and can said information be encrypted?
Kevin states during our discussion that because IndexedDB is a local database, everyone on your local computer and account can access any content saved offline, which means that the browser doesn’t encrypt the database, given that every user on a single computer is assumed to be a trusted individual. Of course, if you choose to, you can create your own encryption mechanism, and plenty of examples of this approach exist in the wild.
For example, Kevin cites the case of a password manager. Some password managers leverage IndexedDB to store passwords and make them available while offline, but a key is required to access those saved passwords. But IndexedDB is in fact a fascinating technology precisely because you can store keys, including RSH keys, in a secure fashion such that your application is incapable of accessing the content associated with the key. Moreover, it cannot transmit the key to other users. Nonetheless, you can store the key for future access and for the purposes of decrypting items.
How Yjs supports offline editing
Yjs and IndexedDB are two peas in a pod when it comes to supporting offline-enabled applications. The Yjs ecosystem includes the y-indexeddb adapter, which represents the connector between Yjs and IndexedDB databases. The y-indexeddb adapter enables developers to store collaborative documents in a local IndexedDB database extremely efficiently. This means that editors can retrieve the document rapidly, and Yjs handles issues of concurrency when many pages are open accessing the same database simultaneously.
These pages can share content through the IndexedDB database, and this is a desirable outcome, because many users frequently have many browser tabs open, which could potentially all be accessing the same content. In order to ameliorate concurrency problems, these browser tabs and users all need to be able to communicate with one another. This offline functionality and synchronization is precisely what IndexedDB offers out of the box.
In recent years, offline applications have become an essential facet of any enterprise organization’s provision of user experiences that are flexible for a wide variety of use cases on the web. Thankfully, with the assistance of emerging web technologies like Yjs, an open-source real-time collaboration framework, and IndexedDB, a browser-based local database that enables offline data access, any developer can benefit from the advantages provided by a bonafide offline application. In addition, with the help of the y-indexeddb adapter for Yjs, you can also facilitate offline collaboration thanks to the deep integration provided between Yjs collaborative editing and IndexedDB storage.
In this blog post, we traversed some of the ideas behind IndexedDB as an additional layer of caching to enable applications with a high standard for performance. In addition, we discussed what IndexedDB is and how it enables offline applications in a graceful fashion. Finally, we covered y-indexeddb, the adapter provided in the Yjs ecosystem for integration with IndexedDB in browsers. In the following installment of this multi-part blog series about offline editing, we discuss how document updates are applied when synchronization occurs in offline applications and how Web Workers can add to your implementation’s capabilities.
For more Yjs content, see Yjs - Add real-time collaboration to any application.