Thoughts on Blaze, ViewModel and MarkoJS


#1

I’ve been using ViewModel with Blaze a lot in my current project, and I have quite a bit of code written. After excluding all things not written by yours truly:

-------------------------------------------------------------------------------
Language                     files       lines of code
-------------------------------------------------------------------------------
JavaScript                     727           62615
SASS                           204           13011
HTML                           461           11946
CSS                            184           10063

Blaze and ViewModel is great and I have very little to complain about them. The speed at which I get stuff done is mind blowing (at least to me). This combo has proven to be quite flexible, for example, part of my app is a very customizable web site builder and Blaze+ViewModel worked wonders on that one. Even so, I’m slightly terrified how Blaze’s development has stalled. @mitar is maintaining the repository, but has himself already moved over to using Vue with Meteor. Last real improvement is from May '17. I’m afraid the next iOS 15 or Android VanillaSyrupPopcorn some day in the future will not work with Blaze and we’re in the ditch.

@manuel has been awesome at fixing minor bugs found in ViewModel, but the recent findings from meteor-web-framework-benchmark suggest that using ViewModel causes a performance penalty of 5-10x compared to plain Blaze, and in the worst case scenario… a lot more. I don’t know if there’s any sensible way to improve ViewModel performance or if @manuel will find the time to do it.

Most of the time my users wouldn’t notice the difference between React and Blaze+ViewModel, but it does occasionally give me trouble, when I end up spending a lot of time rewriting complex component trees to plain Blaze after I notice that rendering on low-end devices is turning out to be painfully slow.

This is especially annoying once one gets used to the comfort of ViewModel :heart_eyes:

During the last couple of years I’ve tried to contribute whenever I can by submitting bug reports, repros and a couple of PR’s to improve Blaze and ViewModel.

I was already considering the idea of giving CPR to both of these projects by committing some serious time to contribute, since I really enjoy the boilerplateless structure of my components and the whole deal of how I write code with Blaze, ViewModel and CSS-Modules. It’s just a joy to build stuff with and I’m not looking forward to giving up and refactoring my 62k lines of JS to 262k lines of React/Preact/Inferno code (though there is ViewModel for React, I have not yet seen any stats on it’s performance compared to plain React).

(Also, React is already starting to look like an underdog, so why bother…)

Then,

just a few days ago, I found out about Ebay’s MarkoJS through HackerNews. It seems to be gaining those Github stars pretty fast. You should read all about it, it has some impressive features.

Rewriting my huge(?) code base of ViewModel components suddenly seems like a task not that impossible, at least if we can make it a team effort!

Here is a component from MarkoJS docs:

class {
  onCreate() {
    this.state = { count: 0 };
  }
  increment(delta) {
    this.state.count += delta;
  }
}
 
$ var count = state.count;
 
<div.click-count>
  <div.count class={ positive: count > 0, negative: count < 0 }>
    ${count}
  </div>
  <button on-click('increment', -1)>
    -1
  </button>
  <button on-click('increment', 1)>
    +1
  </button>
</div>

Can you see why I instantly fell in love? :heart_eyes: Look at the simplicity and lack of crap!

I’ll write the same with ViewModel:

Template.click-count.viewmodel({
  count: 0,
  onCreated() {
    // This isn't really needed, as we can declare initial state above
    // this.count(0);
  },

  increment(delta) {
    this.count(this.count() + delta);
  }
});

<template name="click-count">
<div class="click-count">
   <div {{b "class: { positive: count > 0, negative: count < 0 }"}} class="count">
      {{count}}
   </div>
   <button {{b "click: increment(-1)"}}>
      -1
   </button>
   <button {{b "click: increment(1)"}}>
      +1
   </button>
</div>
</template>

Of course this is not a full similarity check, but even after reading all the docs of MarkoJS… to me it seems like building a transpiler to close the gap isn’t impossible. I think @manuel has actually experimented with some VM code transpilers in the past, maybe you have a better guess?

What about creating a BlazingFastViewModeledMarkos-package with a modified fork of MarkoJS to enable 1:1 syntax compatibility…

Or, maybe @manuel is already building viewmodel-markojs package that has maybe 20 lines of code for full compatibility :slight_smile: My instinct says it should be way easier than with React!

At least for Vue and React there are already some compatibility packages for Tracker. Maybe there could be an effort to make that universal and easily applied to any frontend framework.

If none of these work, I guess I could just write some regexes and spend a weekend hammering the keyboard if integrations are otherwise doable.

Anyway, these are just some ideas I got :thinking: (Also I’m pretty high on pain killers after an accident last friday)

Please shoot them down!

p.s. I absolutely did not test that my code actually works, but it should be close…

p.p.s Should MarkoJS become the next React in near future, imagine if MDG provided an easy upgrade path / escape hatch for all those Meteor users stuck with Blaze…?


#2

I was thinking the exact same thing when I discovered MarkoJS. And I was also having the exact same worries as you about Viewmodel + Blaze.

Viewmodel+Blaze is one of the best combi’s ever (if not the best) for front-end development, but honestly, I think this combi died a while ago. Both repro’s are not developed anymore, and now we’re stuck with legacy code. It works great, but it has performance problems and sometimes weird errors. Not to mention, the world is moving on.

I also use React a lot, and I’ve said it before on this forum: React brought a fantastic idea into the world but the implementation is just incredibly poor. Compared to Blaze+Viewmodel, React is just a pain in the ass. It makes simple things more complex, and it needs in a lot of boilerplate code.

And then I discovered MarkoJS recently, I got super excited. It’s beautiful simple like Blaze+Viewmodel.

Your idea to migrate from Viewmodel to MarkoJS is very interesting. It might work but then we’d also need reactivity / data fetching for Meteor, like we have for React.


#3

Marko seems pretty interesting. I wonder what it does that makes it so much faster than Vue (at least in some artificial tests). I hope that Vue can learn from it and catch up, now that I’m kind of invested in it hehe. Though I guess if Blaze is “good enough”, Vue definitely is!

The main problem I have with Blaze is really that it’s so sluggish compared to React/Vue/Marko (especially noticable on mobile devices). It doesn’t feel very “premium” when the app chugs on every view change (why people used to hate webview apps). Switching our app over to Vue made a big difference.


#4

PS, I still think Viewmodel is superior to Marko because you can just do this.count() to fetch the count instead of having to do this.state.count.

But it is already a major improvement to React, where you might have to do this.props.count or this.state.count, depending on where your count lives. And if it lives in state you need to do this.setState({count: 5}) (which is async and just look at the amount of code you have to write…)


#5

@arggh

Thanks so much for sharing this! Haven’t heard of MarkoJS until now. The performance vs other libs is amazing.
I love how events are directly coded into the HTML (vs Template. < name > .events).

The challenges now (in my humble opinion):

  • Meteor-style reactivity in template methods
  • Data passing between templates (e.g. we have access to template.currentData() which is a reactive source)
  • Code migration from Blaze

[Edited to correct misconception about how MarkoJS does diff-ing with V/DOM]


#6

@amitsaxena777 - Check it out.


#7

Nonsense, Marko on the browser uses Virtual DOM and VDOM diff/patching just like React since it’s currently the most efficient way.


#8

Thanks @Matteo_Saporiti
I went over it a bit too fast as it was getting past my bed time. Will correct my post so it’s not misleading.

Do note that in English, the use of words such as “nonsense” is considered derogatory and dismissive. I disagree that DOM / VDOM is the most efficient way. Comparing data at the string / numeric level before re-rendering should be more efficient.

I wonder why MarkoJS is more efficient, ReactJS has a lot of investment in it. It must be architectural somewhere. 3x faster on desktops and 4x on mobile.

Will research it …


#9

The nonsense part was referring to Marko being faster because it worked differently. It’s not and Marko’s inner workings are well documented so I think you arrived at the conclusion before investigating the topic.

I have no issues with your opinion about VDOM not being a good solution (I’m not sure I agree though) so I’m sorry if I gave you the idea I was dismissing your opinion.
Also note that all VDOM library still have automatic/optional optimizations based on data, but it’s a complex topic and it’s not so simple to decide if a component should re-render or not.
For example in React you can write custom logic in shouldComponentUpdate() to prevent unnecessary re-rendering.


#10

Right, so just be careful with aggressive words such as ‘nonsense’, especially when it’s the first word in your topic. Rubbing people the wrong way even if the intent is noble.

Thanks for your note on VDOM diff-ing.