Help me understand Blaze difficulties with "large apps"

I’m at the early stages of a project, and of course experiencing the Blaze/React dilemma.

I have worked with Blaze in the past, but never to the extent where I encountered the maintenance or problems numerous people have mentioned about Blaze.

So can the forum help me understand what these issues are?

We’re covering all of these concepts in the Blaze Guide.

As background, it is also a good idea to read the UI/UX article in the guide, which talks about some good ideas for writing UIs in general: http://guide.meteor.com/ui-ux.html

Having pasted a lot of links, here’s a quick summary:

  1. Data context is too implicit - it’s not always clear what data is being passed where in a Meteor app. For this reason we’re recommending validating the data context you are passing into your templates (just like React has propTypes)
  2. It can be easy to end up in a situation where your UI is re-rendering all of the time because you don’t understand your data dependencies. This is probably the hardest issue to solve, but can be controlled by carefully following a smart/pure component division in your app: http://guide.meteor.com/ui-ux.html#components
  3. Spacebars doesn’t include support for JS expressions inline, so you sometimes need to write a lot of helpers to achieve simple things. This means when you’re reading your code you have to go back and forth between the template and the JS to understand what’s going on.

There are a couple more I might have missed, but I believe they are all covered in the Blaze guide article, which should be deployed to the live site soon.

2 Likes

Just based on experience you get into trouble with the points @sashko writes when you have bigger templates. In general we make very small templates and that solves it also. Until now never seen issues with it. Also it’s simple to understand because you have a small template and maybe a small helper.

What we do is we separate code:

Template: simple if/else stuff
Helpers: bit more complex logic but never business logic
Objects: the real business logic

Just using native Meteor without packages which promote different systems.

So to answer the 3 points:

  1. Data context too implicit: Does not happen in practice, start splitting up the template.
  2. Re-rendering: Yes can happen but also much less risk because templates are having less trigger to re-render itself.
  3. JS support inline: Correct, that complexity is in general not needed.

Personally I think you will more likely get into issues with onRendered and onCreated. That’s much harder to structure for things like animations, loading indicators and other stuff. But just for showing the right data at the right moment I suspect not much issues.

Does not mean React is not interesting btw, that has a lot of other advantages.

I’ve also run into slow rendering for components with a lot of nested nodes (such as a nested menu with about 200 items). It’s hard to know if it would be any better with React, though.

@loren wrote about it here: https://medium.com/parlay-engineering/fixing-your-meteor-app-s-render-performance-a727e918511c#.8cyc2utx2

1 Like

Very interesting video! Agree, much data or elements can give performance issues. Until now I have not seen any real blocking issue on that which is truly a Blaze issue. More likely it’s an app issue with too many updates, just too much data for a browser at all or other situations happening.

You example of that nested menu is an interesting one. If we would be doing old school PHP or something we would just cache the HTML and we would be done. Trigger on a category update to refresh the cache.

For Meteor it might be an observe on the server which updates a single json document maybe? Or do you use all those categories actually on that page?

Well, what I ended up doing is displaying the menu collapsed on load, and only expanding its branches as needed; instead of what I was originally doing, which was displaying everything, and then hiding/showing branches using CSS.

So yeah, there are always workarounds. But I would rather hit the point where those workarounds are needed later than sooner…

Totally agree also a nice solution!

@sashko , would it be helpful to have a package that would throw console warning errors when a template does not have the data it expects? (like React) For example something like this:

/* global Types */   // package

propTypes(someData, {
  name: Types.string.isOptional,
  baz: Types.string.isRequired,
})

and under the covers it could do something like this:

function propTypes(data, propTypes) {
  if (__DEV__) {
    // validate with Match.test
  } else {
    // noop
  }
}

I can see it being super helpful for documentation and validating code but I imagine that most Blaze users won’t like the extra code and ‘work’?

It would be really cool if it was easy to declaratively set this up with the template like this:

Template.Post.propTypes({
  name: Types.string.isRequired,
  desc: Types.string.isOptional,
})

If you read the blaze article were already doing something very similar with simpleschema. I’d be on board with a package that automates it!

1 Like

With Typescript you have to define for each React “class” the props passed in.
If you forget to pass props from the parent, Typescript will complain in the parent file.
If you use props in the component that have not been defined in the interface, Typescript will complains also.

Now, the problem is that at the moment there are no way to define for the Typescript compiler the interface used by getMeteorData, hence the compiler is complaining that this.data.foo does not exist. There is probably a way to do it, but my definitions-fu is too low to know how to.

About Meteor and big projects, i personnally think that problems comes not from Blaze but from other area, specifically :

  • intensive use of global variables like Session (can be somewhat circumvented with ReactiveDict)
  • no way outside of packages to define load-order/import (will probably be solved by 1.3)

Currently, what i find strange with React is the pattern to use only dumb components and to bring up in the tree data and logic. While i get the benefits of having pure render function, it seems to me that putting all state in one place bring us back to something that is not far from mutable global variable. Perhaps there is something i’m not gettin there.