ryansolid / ko-jsx

An alternative JSX renderer for Knockout.js
MIT License
38 stars 0 forks source link

Bundle size #2

Closed andymans closed 5 years ago

andymans commented 5 years ago

Obvs, the bundle size of this is unnecessarily large as ko does not support tree-shaking. I wonder if you've seen this:

https://github.com/jbreckmckye/trkl

It'd be v interesting to see how it runs with your jsx-dom-expressions.

ryansolid commented 5 years ago

No that's cool. I have been looking at some alternative library examples just today. I was seeing if Vue or Ember's observable/computeds were extractable but they don't seem to be. And I was just looking at Nx Observables, but they don't have an ignore/peek mechanism. So far S.js has been the most compact solution I've used.

There is TKO which has a treeshakeable version of Knockout but it has a bit of a performance hit. TRKL doesn't seem to have a peek/ignore mechanism which is the only thing preventing me from using it as is with Dom Expressions. Mind you it's like a 2 liner change. Probably at odds with the purpose of that project but very easy to fork. I might just do it for fun.

andymans commented 5 years ago

Look fwd to seeing the result! Apropos Ember & Vue - I think that Vue 1.x (prior to the move to Virtual DOM) might have exposed its observables; but the rewrite to v2.x buried everything. Re Ember, having just come off a large Ember.js project I can't comment on that framework without a qualified psychiatrist in attendance!! :-) Raynos also had some nice Observ, Observ-Array, and computeds going on in Mercury a few years back - I've actually used them with Svelte 3 and they perform quite well at only a cpl kb.

ryansolid commented 5 years ago

Yeah the move to Virtual DOM tended to hide away those implementation details. After the popularity of React Hooks, Vue is exposing observables again but not Computeds as far as I can see. Vue has taken approach similar to Ember where the Data is atomic (you can just make an Ember Object etc) but the Computeds only exist as property descriptions on the Component Object.

Ironically the Virtual DOM was never the solution from my perspective, and is now the bottleneck. The problem was many of these libraries hadn't made the move to strictly control their change mechanism.

I did quickly mod TRKL to see if something could be done to support DOM expressions. It's completely doable. Adding an ignore function looks like:

trkl["ignore"] = function(fn) {
  const prevComputedTracker = computedTracker;
  computedTracker = [];
  const ret = fn();
  computedTracker = prevComputedTracker;
  return ret;
}

And with a little tweak to the dispose logic to fit their unsubscribe pattern it basically is a direct swap in for Knockout in this library.

It just lacks a couple features that lend to that strict control I was referring too. A naive approach could be taken like Knockout to Defer Updates and while I don't use that in the benchmarks for KO JSX. Realistically S.js is probably just the better move as it's API is almost identical and it supports synchronous batching. Majority of the remaining Kilobytes comes from the rendering runtime supporting advanced features like Suspense and Portals. So while I could probably shrink the minified build by ~1-2 kb of S.js + DOM Expressions it probably isn't worth it. Technically I haven't made an S-JSX as of yet even though literally writing this would do it:

import { createRuntime } from 'dom-expressions';
const r = createRuntime({
  wrap: S.makeComputationNode,
  root: S.root,
  cleanup: S.cleanup,
  sample: S.sample
});

export { r }

The full code is the basis for Solid's rendering which is available here: https://github.com/ryansolid/solid/blob/master/src/dom/index.ts. Thanks to tree shaking Solid can be used this way without importing the State object which has minimal overhead over just using Signals straight. But I have to admit Bundle size is like 4th in my order of priorities for performance. I take execution performance, memory overhead, and developer expressiveness (reduction of LOCs) above bundle size.

andymans commented 5 years ago

Ha! That looks awesome. Will give it a try-out. I made a half-baked attempt to modify trkl by just copying knockout's ignoreDependencies logic the other evening...but it only 50% worked...now I can see why - I wasn't even looking at the computedTracker. Agree with you - bundle size not a priority issue, while performance naturally is. I'm sure the size will come down in any case with some tweaking over time; but it's already perfectly acceptable. I just did a prod build with mobx (huge) which came down to a reasonable 52kb without gzipping. Set against the size in MB of a typical Ember app, this is all very pleasing!

andymans commented 5 years ago

Just started looking at Solid in earnest. Nice work! Will have a thorough play around w/ it over the wk/end.