alpine-collective/alpinejs-devtools

Rework backend <-> panel/state messaging

HugoDF opened this issue · 1 comments

The way the messaging works is a bit confusing, and I think it's one of the performance bottlenecks (see #10 as far as I've seen, the bottleneck is not the DOM, it's doing massive JSON.stringify's and sending the generated string over a message, then parsing it on the other side).

Currently, when we load backend.js, we crawl the DOM and send the state of all the components (component name, id + all the data we need to render the "data" pane) to the panel. Same when there's a mutation observer update.

Here's the proposal for more granular messaging, it came up in the last paragraph of #169 (comment):

What we could do for the component data refresh is do it under the hood when a "component" gets selected in the left pane (that would be good for an eventual move to more granular data loading: first load components/names, when a component gets selected, load the relevant data).

There's a prior (aborted) attempt at solving this: #46, but the codebase is now in a better state (eg. Cypress tests vs tightly coupled Jest unit tests) so we might be able to land the change this time.

1. on backend.js injection

  • send a "set-version" message with: Alpine version
  • send a "set-components" components on the page (component id + relevant data to populate the left pane of the "components" tab)

Note: this means we don't have any component data in the panel

2. on panel left pane "component" click

  • send a "get-data" message with "componentId"
  • backend receives "get-data"
    • finds the component
    • sends back "set-data" message, with "componentId" + "data" (JSON.stringify(__x.$data) or similar)

3. on mutation observer update

  • if number of components has changed: send "set-components" with all components (id + relevant data)
  • for each component that has changed, re-send "set-data"
    • Note: we could do this for all components depending on how hard it is to detect what's changed
    • Note 2: we could also keep track of which component (if any) is currently open and only re-send that, might be more confusing than useful though

Other Messages

"hover" and "error" should all work same as they do now, (they're pretty independent from the above "component" messages)

Code improvements

It's probably worthwhile to try extracting the message names to a constants file. Worth doing at the end (when the new messaging is working)

Performance

A good benchmark is the devtools load time for https://alpinetoolbox.com/ before and after the updated messaging, if the updated messaging makes it faster to interact, we can close #10 .

Seems that lazy-loading the component data makes the devtools feel less snappy (there's a delay between clicking a component and the data appearing since we're doing a messaging round-trip).

A workaround for this is to send the "get-data" message on component name hover and display on click (see the PR).

Side-effect of doing "get-data" on hover is that we need to ignore duplicated requests to get data (otherwise the expensive "get-data"/"set-data" message payload generation gets run multiple times), again see PR.