Where should routing code in Meteor be placed?


#1

In my Meteor app, I have some routing code in \client\routing.js

But I don’t know if this is where it should be; should it be in my \both* folder instead?

  • Some people name that folder “lib”, but I think “both” is a better name for that folder, as things in it (not being in either “client” or “server”) are accessible from both the client and the server.

#2

It should be placed somewhere:

  • available to both the client and the server
  • loaded before template code gets loaded

Hence the usage of lib which is a special folder. Check out the example file structure section from http://docs.meteor.com/#/full/structuringyourapp


#3

From a naming perspective, this makes no sense to me. Would someone tell me how we got there?


#4

@steve you should ask that to MDG, it is their own convention. lib is a special folder. Please read http://docs.meteor.com/#/full/structuringyourapp


#5

Well, “someone” includes MDG :- )


#6

Hey there,
actually it should not matter where you put your routing code – the only thing that matters is that you can completely control the configuration / startup phase of your app. Ideally the rendering of a specific route / template should kickoff everything that’s necessary for you app to run (routing should not be mixed into the rest of your app code). So the routing layer is like the initiator that decides when your app starts, and what should be rendered. The app itself knows nothing about routing (or that there even is something like flow-router / iron-router behind it).

How you can achieve this?

  1. You need to architect your app code in a way that allows for full configuration and control. You always have to ask: “Would i be able to write an integration test for my complete application where i can configure / startup as many times as i want without much hassle?”
  2. Clean separation of concerns: There is 1.routing (the URL in the browser), 2. layout rendering and 3. your app code. All of these things are completely separated from each other. Your app is just a bunch of templates / supporting UI logic that can be kicked-off by rendering it. It does not know that it is rendered by a routing framework (should work the same way when just putting the template tag somewhere)
  3. Communication patterns: So now you decoupled the various concerns, but how can you glue it all together? The simple answer is events. Every layer of your app dispatches events that speak the language of the respective layer. So if you have a view with a login button you should not put the URL to redirect to a certain route in there, but dispatch an event like LoginRequested because the view does not know about routes or how the login system actually works – it only knows that the user clicked that button and requests a login. Other parts of your app can then handle this event and take appropriate actions like redirecting to a certain route / rendering a login view etc. The fantastic thing about decoupling in this way is: you have complete control over the process! If your view simply provides a hard link to /login you have no way to hook into this process of “the user requested to login” – and believe me, there are a lot of scenarios where you first want to check, authenticate or setup things before actually fulfilling such requests.

For a simple example how such a system can look like checkout this TodoMVC application that is built with space:ui

The Space framework was designed from the ground up to organize your app into modular components with a clear configuration / startup phase. If you have any questions we have a nice little community of great devs over in the meteor-space Gitter chat!


#7

I agree; for a product/platform/framework (whatever you want to call it) like Meteor that usually “just makes sense”, “lib” does seem unnecessarily illogical (maybe it’s for historical reasons).

From what I understand, code in any folder other than “client” or “sever” or “private” will run on both. Am I wrong?


#8

Yep, that’s correct. Also, client/lib or lib/client will load only on the client (but before others) etc. And then there is main which loads last, perhaps as an ode to old-school runnable program conventions.