mavoweb / mavo

Create web applications entirely by writing HTML and CSS!
https://mavo.io
MIT License
2.83k stars 177 forks source link

design pattern: base/launcher/satellite apps vs nested mavos or heterogeneous collections #428

Open hopeful2 opened 5 years ago

hopeful2 commented 5 years ago

I mentioned the concept of satellite apps in issue #326 and PR #427. It is probably better to have a separate issue here for brainstorming and discussion in one place.

First of all, I love the Mavo project. I mean it. Mavo has solved a hard problem of editing structured data in originally read-only webpage, with instant preview. It uses very little resources after initialization, and is very performant with hundreds of nodes on modest machines. The proxy to original data is a really helpful design. We have an open source project that to a large part depends on Mavo, using the approach described below. Once the UI and API are fixed, we will release the code and a demo to show how efficient Mavo is.

Up to now Mavo does not have a destroy method yet. I am working on a PR ready for submission once you have approved the required changes in data structure and strategy to manage event listeners. When an instance can be created and destroyed on demand, with memory properly managed, there will be some new and interesting ways to use Mavo. Here is one of the new ways.

the needs for Base/Launcher/Satellite Apps

Big DOM should be avoided if possible. Sometimes big DOM is necessary to keep logically related contents on one page for scrolling up an down, and for a better user experience. Base/Launcher/Satellite Apps are designed for use cases with big DOMs.

Overview of Base/Launcher/Satellite Apps

In this model, some Mavo apps are always activated, some apps are activated and destroyed on demand. Some components work to make the whole system functional, and glue the apps together.

base apps

The base apps are always activated, and take charge of global parameters that can be used in other apps.

satellite apps

The satellite apps are created and destroyed on demand. These apps may be rendered in DOM, or added to the DOM on demand. Similarly, after being destroyed, these apps may stay in the DOM in standby mode, or removed. These are like items in a collection, but can still perform well in a big DOM. These apps can be similar, rendered from the same template, or totally different. they can be turned on or off individually.

launcher

These are buttons attached to a toolbar on the satellite apps to toggle satellite apps on or off, move, clone, or delete. The buttons work before satellite apps are activated.

Some buttons are hidden initially. Toggling on an app will show the buttons, and toggling off an app will hide the buttons. The toolbar can be made visible on hover for example to stay out of the view.

object store

The object store is a big object in memory responsible for receiving data from satellite apps, assembling to the right path, and storing to persistent backend. It has members to load in base apps, and an array to hold data in satellite apps.

satellite app storage adaptor

These are pseudo storage "backend" for satellite apps. Upon loading, the data is fetched from object store, and upon saving, the data is merged into the object store.

the page loading process

Here is an overview of what happens when a page loads. Each section in the description is a satellite app.

performance advantages over nested mavos or heterogeneous collections

While Mavo is very performant AFTER initialization, traversing, parsing a big DOM and updating it is very slow. This is the limitation of browsers and DOM, and can not be totally eliminated. Mavo looks for information from DOM when it initializes, and updates the DOM after loading data. Initializing from a big object and updating a big DOM takes a very long time.

Nested mavos or heterogeneous collections are great concepts. These are fine for small apps, but will probably face the issue of initialization with big object in a big DOM. Some older browsers or older machines may have problem loading the page.

With the satellite model, some apps are activated upon page load, while others are activated upon clicking a button later. this progressive approach greatly reduces the resources required at initial stage. When an app is done, it can be toggled off saving resources. In our tests, this approach has reduced initial loading time by 70-80%.

The satellite model helps Mavo to handle bigger jobs with low resources. Some templates can be compiled and supplied as JavaScript functions, saving the effort to parse DOM and compile at run time. If it has to traverse the DOM and compile from information found, this can be done asynchronously, taking some pressure off the initial loading.

important information to know before trying this recipe

When toggling off an app, the elements (root and children) of the Mavo app must be destroyed and created again. Otherwise the DOM still holds reference to these elements, preventing WeakMaps from releasing resources for garbage collection. that will defeat the whole point of toggling off the app.

If you find this concept useful, some resources may be allocated to development on this approach. Some of the code from our project can be merged into the core library, or made available as a plugin, so developers don't have to write similar code trying to achieve the same outcome.

Comments and suggestions are welcome.

hopeful2 commented 5 years ago

I have pushed a demo of our project with tutorials to github, and the project uses the concept described above to solve the problem at initial loading. here is the link to the base/satellite app demo.

what do you think about this approach?

LeaVerou commented 5 years ago

Hi @hopeful2! This looks like a really cool project, but I couldn't figure out exactly how Mavo is used in it. Do you want to explain a bit about it? :)

hopeful2 commented 5 years ago

OK. It is easier to explain this model now with a working example, and a real use case.

Our project aims to empower users to create content quickly in the browser without writing code. It is much faster to create content directly in the browser, see the result and make changes, even for developers. I wrote some of the tutorials in presentation style, at a speed I could never achieve before with other tools. In this aspect Mavo is really awesome.

the use case of a big DOM

The use case requires a big DOM and very different sections. From users' point of view, it is easier to edit one section and be able to see the sections before and after, and change the order of sections if necessary. 30 sections are reasonable to expect when preparing for a talk, though most landing pages will have less.

The sections are essentially heterogeneous items in a collection.

the challenge of initial loading

However due to the limitation of DOM, it is a challenge to load the page and instantiate Mavo instances when there are many sections. Too many sections will crash a browser, especially on mobile phones. it is hard to define "too many" as 30 sections are OK on a laptop, but could be too heavy for an old phone. Users don't know a link is too heavy for their phones. It is very bad user experience if they navigate to a link and the page won't load. or even worse, the browser simply crashes.

The heterogeneous items or nested apps, if implemented in Mavo, will face similar performance issues.

the solution of lazy instantiation

as I wrote before, our project uses base app/satellite app to solve this problem.

the base apps

The base apps are Mavo apps assigned to a more important role to look after sibling Mavo apps. The base apps are always on, and stores information for other apps. we have the following set up:

satellite apps

Each section (including header and footer) is a detached satellite Mavo app, and is rendered from a template on client side.

The key is to render the template with saved data for preview, but do not instantiate Mavo before user interaction. After editing a section, users can toggle off the app and release resources for gc. This way a page can handle more sections, and load properly on mobile phone too.

satellite apps are different from heterogeneous items or nested apps. satellite apps are independent and can be individually toggled on or off. This will take the pressure away from initial page loading. Some satellite apps load data from page app or site app, and provide the functionality of heterogeneous items or nested apps.

mobile launchers

There are buttons to manage sections on each section, such as move a section up or down, insert section and delete section. These buttons are functional before instantiating the satellite Mavo apps.

Our project is used as a page builder at the moment, and is designed in a way to share templates with Hugo. It can edit data and feed data to Hugo for server side rendering, with or without Mavo editor. With some modification, it can serve as a user interface for any headless application. Mavo has made it really easy.

If you think some features are useful and would like to include in the core library or offer as a plugin, we can extract the code and submit PRs. we use mv-action heavily in the project as it is a free ride on the event listeners and DOM operations that Mavo is already doing. I hope the API for mv-action can be stabalized soon.

if you have more questions, please let me know.