atlassubbed
Joined 8 years ago
Joined 8 years ago
const { diff } = require("atlas-relax");
const DOMRenderer = require("atlas-mini-dom");
const App = () => (
<div>
Bonsly evolves into Sudowoodo after learning mimic.
</div>
)
// create a DOMRenderer plugin
const rootEl = document.getElementById("root");
const renderingPlugin = new DOMRenderer(rootEl);
// mount <App/> against the "null" DAG and render it to the DOM.
diff(<App/>, null, renderingPlugin);
The cool thing is you could diff two different DAGs against each other and listen to the delta, like `diff(<App1/>, <App2/>, consoleLogPlugin)`. The base library could be used to generate application frameworks as long as your application framework can be thought of as a DAG operating on data. React is an example of such a framework, but so is something like Airflow, so you could write a plugin that lets you build your own kind of Airflow. That was the motivation behind my DAG abstraction -- to make it easy to create DAG frameworks for frontend and backend. Let the base library do all the hard reconciliation work, and you can build application frameworks on top.Anyway that was all mostly an exercise. I didn't end up using my framework for anything more than a state management solution for React. It handles global data perfectly, although these days React context or hook management is usually enough.
It's a DAG-computing framework in JS that allows you to listen to updates in a compute graph. It's a set of legos that I used to build both a MobX clone (https://github.com/atlassubbed/atlas-munchlax) and a React clone (https://github.com/atlassubbed/atlas-mini-dom). React and MobX are actually the same thing mathematically: reactive DAGs, so they can both be built using the exact same abstraction.
If you end up using this library, please let me know how it turns out! I'd love to see a demo of exactly what you're talking about. I ended writing quite a bit of mouse-event and panning/zooming code on top of ngraph so maybe this might be easier?
[0] http://bigocheatsheet.com/
[1] https://github.com/anvaka/ngraph.pixel
Sure, there are issues with existing VDOM implementations that do not do these compile-time optimizations:
1. Returning new JSX elements from every render
2. Building key indexes for every subdiff
The first issue can be solved with application-specified memoization in render. The second issue is pretty hard to avoid if you want to avoid matching elements based on indexes (naive subdiffs). Implicit and explicit keys are there for a reason, namely that moving elements is assumed to be a much less expensive operation than unmounting and re-mounting them. The O(N) trash memory overhead per subdiff incurred due to key indexes is justified, in my opinion. If using an algorithm like LCS, you'll incur more time/space cost, but you will even further minimize the edit path.If I'm not mistaken, Imba would have to use something similar to key indexes if they want to avoid unnecessary unmounting and re-mounting for templates which are composed of large dynamic lists.
I'm not sold on Imba's value proposition. The value proposition is compile-time memoization for static elements, so you avoid re-creating those templates during renders. That's great and all, but how much of SPA webapps are purely static elements? For example, consider the the following JSX template:
<ul>
{this.state.bigList.map(i => <li>${i}</li>)}
</ul>
I don't think Imba would perform much better than these other libraries for templates which are 99% dynamic (like this one), and so the dominating term here is the subdiff term, where you will end up either: 1. Creating at least O(N) trash memory (e.g. key indexes)
2. Doing unnecessary mounts and unmounts