Slow or intermittent connections are an all-too-common case that many users face when attempting to work with applications. Offline-enabled applications are a particularly challenging use case because they require synchronization and a local understanding of data. Thankfully, with the help of Yjs, an open-source real-time collaboration framework, and IndexedDB, a browser-based local database optimized for offline content, anyone can build an offline-enabled application that also includes features for rich collaboration. When combined with the functionality provided by y-indexeddb, the adapter for IndexedDB in Yjs, developers can make use of a wide variety of features that aid progress towards an authentically offline-first application.
A short while ago, I (Preston So, Editor in Chief at Tag1 and author of Decoupled Drupal in Practice) had the unique opportunity to moderate an enthralling dialogue on the Tag1 Team Talks show about how Yjs empowers offline-first applications with the support of my Tag1 co-workers 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 to build offline applications with Yjs. In this installment, we cover how offline editing could function in Drupal and the important question of how Web Workers figure into the equation.
How offline editing could work in Drupal
Before we kick off our discussion of offline editing and its prospective incorporation into Drupal, I encourage you to check out the first and second installments of this blog series about offline editing with Yjs in order to gain a complete understanding of what is involved when building offline applications, particularly the spectrum of possibilities enabled by technologies like Service Workers and IndexedDB. The previous installment of this series also includes discussion of y-indexeddb, the Yjs adapter for IndexedDB and a key bridge for offline functionality.
Illustrating offline editing examples
During our Tag1 Team Talks episode, Fabian encouraged the audience to consider a real-world use case when it comes to content management that many practitioners of content management systems (CMS) are doubtlessly familiar with. Consider a situation in which you have dozens of tabs open, and you are editing content in your CMS of choice. Now consider the scenario in which you leave your computer and return later to continue working, forgetting in the process that you have a Drupal article open in your CMS on your browser.
Then, in the Drupal CMS, you return to your administrative interface, logging in and editing your content, which is all present thanks to offline persistence of your data locally. Everything you have modified in the content is already present automatically; you don’t have to do anything else. Now, you can access your content on another tab in your browser of a different draft that you had edited previously. This illustrates the importance of counting on conflict resolution when it comes to managing offline editing on varied systems.
Now consider another scenario in which we are editing a Drupal.org issue. Upon a typical computer crash and power outage, we lose access to the internet and thus connectivity to the most up-to-date status of an issue on Drupal.org. If the Drupal.org issue were to be connected locally to our IndexedDB database via y-indexeddb, all of the content we had created for a particular issue would still be available, and therefore we wouldn’t lose any content in the process of reconnecting.
This is a significant problem that often seems insurmountable, especially given the fact that Drupal’s Autosave module, which permits automatic saves on keystrokes in Drupal’s editorial interface, can prove problematic in this environment. After all, what happens when a save to the server is impossible due to the lack of a stable connection? Though other APIs exist, such as HTML5 Local Storage, this approach only works to some extent and does not alleviate the fact that multiple tabs containing different modifications to the same content may be open at the same time on a user’s browser.
Service Workers and IndexedDB
Kevin offered another compelling use case during our comprehensive conversation on our recent Tag1 Team Talks episode about enabling Yjs offline editing. While a web browser crashing or losing internet connectivity is nothing new, flight passengers have unique situations that require substantial delays in synchronizing once again with the server. (For instance, your correspondent is, at this very moment, writing this blog post offline on a plane without any access to the internet, even though other modifications could be occurring in the content I’m currently editing.)
Fortunately, because Service Workers have access to your local IndexedDB database, the browser will be able to successfully sync your content to your server such that other applications can see what you edited, as soon as you reconnect. This means that you can create offline-enabled applications that are progressively enhanced and also support use cases in Drupal that require collaboratively edited documents to be made possible through the emerging web technologies we have described over the course of this series.
Supporting collaborative editing in Drupal
Consider, for example, the case of a document in Drupal that is collaboratively edited over the course of time by many users. You, however, are a user who has just gone offline. Nonetheless, you immediately see content display in Drupal, because there is no need to wait for the server, because all local content is served from the IndexedDB database that is currently housing your data offline. And instead of exchanging the entire document, y-indexeddb will ensure that only the parts that are modified are exchanged.
In the process, the server will send to you an update of the content that was created in the meantime by other users while you were disconnected, and you will, in a corresponding fashion, submit to the server an update representing the content you modified and updated over the course of your offline editing. Thus, we can see that y-indexeddb is a compelling enhancement to any web application that requires collaboration if you wish to build an offline-first application that also comes with effective performance optimizations out of the box. As Fabian joked on our recent Tag1 Team Talks episode, such offline-first functionality is nothing short of material from a James Bond movie, because if there’s no internet, you can still ensure that data is sent to the server in any secret agent scenario.
What about Web Workers?
Service Workers and IndexedDB are the stars when it comes to enabling offline-enabled applications with collaborative editing, but how do Web Workers figure in the picture? Web Workers, after all, are an additional browser API available in addition to Service Workers that allow applications to perform computationally complex calculations. For instance, if you need to perform major reconciliation on a Yjs document that is being collaboratively edited, you can initialize a Web Worker that retrieves a Yjs document from the local IndexedDB database and performs said calculations before executing an extremely expensive synchronization job to match up with the data held by the server.
In addition, if you wish to render an HTML page based on the data that is present in the Yjs document and subsequently send it to the main thread, Web Workers make these heavy computations possible with as much efficiency as possible. And in the process, this also allows you to exchnage data through IndexedDB across browser contexts. In short, IndexedDB is a local database that multiple processes can access concurrently and leverage to accomplish different necessary tasks.
Extending Service Workers with WebSockets
The aforementioned Service Worker in question, as Kevin admits, may also wish to establish a WebSocket connection to the server in order to synchronize the data or even leverage a different technology besides WebSockets to sync the data as needed. The main thread, that is, your website, doesn’t necessarily need to sync data through WebSockets in a real-time fashion. During our Tag1 Team Talks episode, Fabian illustrated a case in which many changes on your local environment need to be synchronized without conflicts to the server, something achievable thanks to Yjs.
Conflict resolution through Yjs still engenders some latency, and after all, as end users, we are loath to wait even more than a few seconds for content to be updated. Many of us react with annoyance when presented with a spinning loader reflecting the extensive content synchronization required. If you place all of this capacity in a Web Worker instead, you can proceed to modify your document and view live changes that have been synchronized with the server, and all of this occurs in the background. A Web Worker gives you a means for all the interactions to occur without blocking the interaction that users conduct, a very important consideration for performance enthusiasts.
Modern web development has wrought many changes in the front-end landscape, but perhaps no emergence of new web technologies has been as influential for enterprise organizations as the advent of offline-enabled applications that allow collaborators to synchronize changes to the server as needed but retain all functionality when connectivity is unavailable. Fortunately, with the increasing popularity of Yjs, an open-source real-time collaboration framework, and IndexedDB, a local database solution for housing data needed offline, developers have never had it easier when it comes to implementing offline applications that also support collaborative editing.
In this blog post, we traced some of the ways in which offline applications can be at the forefront rather than an afterthought in Drupal’s own ecosystem. We also analyzed how Web Workers can enhance an offline application to provide even more functionality. In the next installment in this multi-part blog series about offline editing with Yjs, we discuss how y-webrtc, the subject of a previous Tag1 Team Talks episode, intersects with the features that Yjs provides for offline collaboration.