ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect…

Follow publication

Cross browser window state management

--

This new approach is extremely powerful, yet easy to use.

The implementation relies on using SharedWorkers.

Content

  1. The demo app in action
  2. The magic inside the application architecture
  3. Bindings to access the state data
  4. Online demo
  5. More infos about state management in neo.mjs
  6. Can we get a standalone repository for this demo?

1. The demo app in action

I kept the demo app as simple as possible.

Here is a short video to see what we are going to talk about:

2. The magic inside the application architecture

The autogenerated index file:

We are using the useSharedWorkers framework config to switch from using normal web workers to shared ones (required for the multi window context).

We are pointing to our app.mjs file.

The window (main thread) will not include it. Instead, it will get picked up by the application worker (separate thread → CPU).

Both apps start with just an empty Viewport:

The main app is using a ViewportController:

[Side note] With webpack ^5.35.1 we can finally use public class fields inside the dist/* output.

Inside the SharedWorkers scope, we can use the connect and disconnect events, which happen when a main thread arrives or leaves. This includes the current app as well.

onAppConnect() is already the key part of this article.

When the first app (browser window) connects, we will create a view model containing the state (data).

All apps which connect afterwards will receive a parent reference to this model.

“View model” inside the neo.mjs context means an entirely optional construct to make data accessible for child components.

In fact, this one view model is the only one both apps are using (in case we don’t count pure parent reference models).

3. Bindings to access the state data

Both Viewports add this MainContainer:

The label inside our header toolbar contains a bound text config.

We are using template literals and can access the entire parent model chain to automatically find the closest match for each data property.

Inside our view controller, we will just lazy load the dialog JS module in case it is not there yet and again point a parent reference to the closest model.

By default, models will find their closest parent automatically, but dialogs are special, since they live outside of the component tree (direct child nodes of document.body .

Inside the dialog view, we are binding our two TextFields value config to our model data.

We also add change listeners which we will receive inside the closest view controller.

We are using this.getModel().setData() which accesses the closest view model for each data property.

Correct, this means the view model of our first app, even in case it lives inside a different browser window.

This is it. As simple as this.

4. Online demo

Important: Open the main app first, then the child app inside a different window. To “reload” the app, you need to close window2 and reload window1 (a SharedWorker lives until there are no connections left).

We could of course enhance the apps (e.g. adding a Viewport controller to the child app), so that you could open this one first.

Browser support Desktop: Chrome, Edge, Firefox

Main App:
dist/production/examples/model/multiWindow/

Child App:
dist/production/examples/model/multiWindow2/

To access the console, you need to open e.g.:

chrome://inspect/#workers

and then select the app worker (you can terminate them here as well).

For non shared workers, you get all logs inside the “normal” console.

In case you are wondering about Webkit (Safari), here is the related ticket:

5. More infos about state management in neo.mjs

This article is part of the version 2 release announcement series:

This article points to the previous 2 articles, which contain more background infos on how you can use view models and how they got implemented in detail.

You can find the neo.mjs repository here:

6. Can we get a standalone repository for this demo?

Already got this question and the answer is yes:

While you can use npx neo-app to create your own workspace, it might be convenient to e.g. fork this repo instead and use it as a starting point.

The app content is almost identical, except for adjusted app names:

Neo.examples.model.multiWindow is ok for examples inside the framework repo, but normally app names are short. MyApp and MyApp2 here.

The view content also got moved into a view folder.

Best regards & happy coding,
Tobias

--

--

Published in ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

No responses yet

Write a response