MeteorFlux Flow

Hi there everyone!

I am about to start coding a project in Meteor and I want to use some kind of architecture.
I want something very simple, but which won’t become a nightmare in the future.

I took a quick look at Flux and I loved it. I have coded in the past using PureMVC so I am familiar with that kind of “notification centred” MVC framework. But what I used to hate about PureMVC is that you have to write a lot of boilerplate code here and there, which sometimes is not only time consuming but hard to follow. And it was very painful to do something reactive as well.

So, here it comes Meteor, the super simple reactive framework with no architecture.
And here it comes Flux, a new MV* architecture designed by Facebook to fit their reactive frontend (React) better than what a normal MVC does today.

React is quite similar to Blaze, but with Meteor we have tons of other good stuff already there. So Meteor and Flux may be a perfect match. I actually think that it should be simpler to use Flux within Meteor than with React!

I’ve been reading all this stuff. If you never heard of Flux, take a look:

So the Flux Dispatcher is the only part needed to be able to use Flux in an app, and it’s very simple: 150 lines of code. The code is pretty straightforward as well.

I could rewrite it to adapt it to the Meteor needs, or make a package around the original, not sure what’s best right now.

But first of all, I have made a graph of a possible Meteor Flux Flow and I’d love to get some feedback. What’s wrong, what’s missing, what may not work…

Link to high resolution image

Important things to mention regarding Flux and Meteor:

  • Any event which comes to the App: Views (via Template Events), APIs, Cron Jobs… can only send Actions. They are not allowed to change routes, session variables, collections… directly.
  • The Stores are libraries of callbacks which can act over collections, session variables, routes… They receive the actions and act accordingly. They have both the data and the logic.
  • Finally, the Views re-render automatically (thanks to Meteor) to reflect the changes. They use the Template Helpers as Controller-Views to modify the received data (if necessary).
  • One Action can’t result in triggering another Action. This is by design to prevent chained effects. The dispatcher would throw an error.
  • Stores can wait until other stores have finished their callbacks.
  • Actions can look like this:
    Dispatcher.dispatch( “add_todo_item”, { text: “A new item” } );
18 Likes

You’ve taken a good time to work on this. I like it.

I personally like the Idea of flux at first. They we started to worked on a project to implement that.
Then later we found it pretty hard and a lot of redundancy in code.
We couldn’t found where the Router goes in this flux. Facebook’s original version didn’t had a router and they built it for chat.

Then we simply make the Router as a event dispatcher and remove actions and reactive state. Then, it looks like we are back to square one :smile:

So, after that, we got Flux main principle (unidirectional data flow) and build something on that. It did work for us and we love it.
And it reduces a lot of page re-renders and build apps with predictable reactivity.


But, I still believe, Flux is a good architecture and hope you could find a better way to implement it with Meteor.

2 Likes

Thanks Arunoda, this is the kind of conversation I was looking for. I hope more people jump in :blush:

I totally agree with you: I don’t want redundant code but I love some of the Flux concepts, like the Unidirectional Data Flow, the decoupling of the dispatch system and the limitation that one action can’t trigger another action.

I have kept reading pretty much all I have found about Flux… blog posts, stackoverflow questions, different implementation, code examples… and I really think it can be great.

The only problem I’m seeing right now is that a Facebook Flux app is like this:

But in Meteor, some things can modify directly the App State. I have called them “External Input” in here:

And those things doesn’t trigger actions action. They are:

  • Updates to MiniMongo coming from the server MongoDB. Usually when some other user does something.
  • Changes in the url. Usually when the user enter manually the url (or copy and paste) or hits the back button of the browser.

There may be more I haven’t thought about yet.

I have updated the image to include a new layer called App State:

Link to high resolution

So what I am thinking right now is:

  • In Facebook Flux, it works like this:
    • Stores: Update the app state.
    • Views: Retrieve the app state from the Stores.
  • But I think Meteor Flux it should work like this:
  • Stores: Update the data
  • Views: Retrieve the app state from the App State.

I think it’s time to start coding some examples an see how all this work out.
I will post them here!

2 Likes

I tried RefluxJS for simple ecommerce, simple, less code and less boilerplate than Flux

I’m all for something like this. I started looking into Flux because it describes clearly some features and organizational flow I would like to use.

But I started to think that a lot of the flux features and concepts seem like they are built into Meteor and Blaze,. However, it’s not obvious how to structure these built-in features to create a flow like Flux or PureMVC.

Just giving one example to use Meteor features along the style of flux :
Use Mongo Collections to hold application state (store). An observer can observe changes on those collections (controller-view). I think all we’re missing is a place to hold all the ‘actions’ (Dispatcher) , a good event system (actions) which wouldn’t be too difficult to implement.

thanks

Yes, I am aware of Reflux and I studied it as well. It’s interesting but I don’t see enough benefits to introduce changes to the patter all people know. Besides, they changed the WaitFor() behaviour and their solution (stores can send actions so other stores can update themselves) is going back to chained actions, and that’s what Flux is trying to avoid.

We can build the same kind of helpers on top of the normal Flux dispatcher so there is less boilerplate, but without changing the pattern anyway.

Totally! I think it can be a perfect match with way less code than with React because Meteor already does some of the things automatically for us.

That’s my next step :slight_smile:

I’m going to recode the Facebook dispatcher (to get rid of JSX) and try to create some examples. I will post them here.

1 Like

Hey Arunoda, I’m not sure from your comment on what you ended up with that you like but isn’t flux. Could you elaborate some more or point to an example?

Sure. I like flux because of its unidirectional data flow. Here I think flux is is too much for meteor.

  1. we need most of the apps to be router specific. We build web apps which has more activities in the router. It’s a good idea if we can create a route for every case. Chat is a different example. So, router tends to be a good dispatcher.

  2. Stores. We have minimongo and reactive queries. That’s a better place for stores.

  3. I got confused with their action implementation. May be guys at fb may like to write more codes. It just a single event to me.

What they basically build an even emitter pattern with some more stuff to It which is specific to how fb architect their apps.

They later release another UI architecture, I don’t remember the name. So, it’s like they just throw out different stuff. But should not use all of them. But I like react.

Okay, then what’s the issue with meteor. If we designed a router based app normally, that’s tend to be with unidirectional data flow.

But with IR we re-run stuff in the router layer, with or without our concern. We need to stop that. We did it with flow-router.

In meteor stores get updated automatically. Then the UI also gets updated using reactive queries. Yes, now we don’t have a better control over that. But I couldn’t find a patter which works best for us.

Other things is template is meteor and there is no place to maintain the app state and the logic. We solves this using flow-components. It enforces single direction data flow and prevent talking to parent components.

3 Likes

Arunoda, when did you take a look at Flux? I have seen some outdated posts talking about things which have been improved and their dispatcher is simpler now than it used to be.

I have just thought… that the two things I listed as changing the “App State” without triggering actions can be solved quite easily:

  • Updates to MiniMongo: Those went thru other user’s client dispatcher so data has been properly processed.

  • Changes in the url: You can easily use the onBeforeAction to send a proper action Stores can react to.

    Router.onBeforeAction(function() {
    Dispatcher.dispatch( “URL_HAS_CHANGED”, { url: this.url });
    this.next();
    });
    We can even add a plugin so that behaviour is automatic. Then you can subscribe to that action with the Stores.

I am not following you here.

In Flux, Stores contain the logic of the app, not only the model (Mongo Collections and Session variables).

  • Stores: Contain the logic of the app state.
  • Controller-views: Contain the logic to transform that generic app state data into views the users can see and interact with.

In Meteor, the Controller-view part can be easily done in the Template Helpers.

Could you explain the difference between IronRouter and your FlowRouter?

Seems like dispatcher has simplified. We tried it when it releaed initially.

Flow Router is a router which does not handle rendering. And it does not re-run parts inside the router. Check Readme.

I hope it’s a good fit for this kind of work.

1 Like

That’s what I thought :blush:

I’ve seen your introductory video and it looks like it can be a great match for this!
I’ll try to make it work.


I have just published a first version of the dispatcher:


https://atmospherejs.com/meteorflux/dispatcher

You can add it with:

meteor add meteorflux:dispatcher

Then you can use the three Dispatcher methods:

// Register Store callbacks and receive a token
thisStore.tokenId = Dispatcher.register( thisStore.callback );

// Send actions
Dispatcher.dispatch( { actionType: "SOMETHING_HAPPENED", data: "some data" } );

// Do stuff when actions happen and use waitFor()
thisStore.callback = function(payload){
   switch( payload.actionType ){
       case "SOMETHING_HAPPENED":
           do_something();
           break;
      case "OTHER_THING_HAPPENED":
           // Hold and wait until otherStore has finished processing
           Dispatcher.waitFor([otherStore.tokenId]);
           // Now do something
           do_other_thing();
           break;
    }         
}

I didn’t add a readme yet, but I want to see how this fits with Meteor and if it needs some changes.

Right now is a clone of Facebook’s dispatcher, so you can use it exactly in the same way:


You can see more examples of use in their repo.

I will create some Meteor examples as soon as I can.

Thanks @arunoda . We’re thinking along similar lines.

1 Like

I have created the Todo App example:


http://todoflux.meteor.com/

I think the code is pretty straightforward and easy to understand:

  • Template Helpers: get what they need from the Collections and Session variables.
  • Template Events: emit actions.
  • Stores: subscribe to those actions and update the Collections and Session variables accordingly.

My only concern about this example right now is where the Meteor.methods() should be…

What I like very much about the flux architecture is the dispatcher (a.k.a. Mediator-Pattern). I first found a very good implementation of this pattern with ChaplinJS a framework for backbone.js.

I was also starting to think about implementing flux for meteor but found a pretty solid solution that was already build: space-ui

Space-UI has some more benefits e.g. having complete control over the application and no need to rely on the folder depended load order or even alphabetically one. Also the package-only structure is not needed for the whole application anymore.

What space-ui lacks are components and a router, but if you combine it with the simple flow-router and flow-components (or react.js if you like) I think you have a pretty solid application architecture based on the core concepts of flux.

4 Likes

I’ll take a look at those. Thanks @manuelschoebel!!

I’ve been taken a deep look at the space-ui but that’s the kind of overcomplicated framework I don’t want.
It’s like your are making an app with space-ui and not with Meteor anymore.

By design these frameworks can be great, but in the end, something like this is very slow to code and figuring out how something works is not straightforward because you need to follow complex chains.

For example, the chain of the clearCompleted action in their todo example goes like this:

// event is fired in '/client/views/footer/footer.coffee'
'click #clear-completed': () -> template.mediator.onClearCompletedTodos()

// then it looks like you have to write this in '/client/lib/events.coffee'
CompletedTodosCleared: {}

// then do this in '/client/views/footer/footer_mediator.coffee'
onClearCompletedTodos: -> @publish new CompletedTodosCleared()

// then in '/client/stores/todos_store.coffee'
@handle CompletedTodosCleared, on: -> @commandBus.send new ClearCompletedTodos()

// then write this in '/shared/lib/commands.coffee'
class @ClearCompletedTodos extends Space.messaging.Command
    @type 'ClearCompletedTodos'

// and finally in '/server/todos_controller.coffee' you get to delete the items
@handle ClearCompletedTodos, allowClient: true, on: (command) ->
    @todos.remove isCompleted: true

I love Meteor because everything is as simple as it can be. No boilerplate code anywhere. Everything is straightforward.

The Facebook’s Dispatcher implementation is the minimal amount of API needed to ensure you can follow the Flux principles, and all the other stuff is done with te Meteor tools we already know.

So I am going to stick with the Facebook’s implementation for now and keep working to see if I can find its boundaries.

1 Like

I’ve got to say, your implementation looks pretty darn clean to me (at a quick glance at least). So what was your reasoning for embracing flux, but not react? Obviously (as you’ve proved) they aren’t inseparable, but as they follow the same sort of ethos, I imagined I’d see them used together almost exclusively.

Meteor doesn’t impose you any architecture. That’s a good thing because you can choose the one you prefer, or don’t use any architecture at all.

Coding with an architecture is better, because you don’t have to think where to put your code each time you add something. And it saves you a lot of trouble when the application gets bigger because bugs are easy to find and everything is organised following some pattern.

Flux is a new architecture designed by Facebook for reactive apps. React is one of those. But Meteor is another one. I prefer Meteor over React because it gives you way more than just the front-end.

So I’m just trying to figure out the best way to make Meteor apps with Flux architecture, but with this singularity:

  • Make things as simple as possible, like Meteor does. This means no boilerplate code, complicated APIs or more stuff to learn.
  • Use as many Meteor tools as I can: Spacebars, Template helpers & events, Mongo Collections, Subscriptions, Sessions, Meteor methods… even IronRouter or Arunoda’s Flow Router.

I don’t want to reinvent the wheel.

By the way, any help is welcomed :smile:

Sorry I didn’t mean using Flux and React alone, I meant using the official package: https://github.com/reactjs/react-meteor

As then you’re not replacing Meteor at all, just Blaze.