coopermaruyama / meteor-dust

Meteor boilerplate for large apps
43 stars 10 forks source link

Namespace vs. api.export #4

Closed farshid1 closed 9 years ago

farshid1 commented 9 years ago

Thanks for this great boilerplate. I just have a hard time understanding App.utils.namespace function use inside a package. If we are able to export a module using api.export(MyModule), what is the point of having access to the same object through namespace?

I was also wondering if you could add a sample module that actually implements the provided interface provided by app-lib's App object.

Btw, I'm using coffeescript.

coopermaruyama commented 9 years ago

The reason App.utils.namespace is useful isn't because it lets you export to the global namespace, but rather because it lets you pass the namespaces as strings. This is important in meteor for 2 reasons:

The first reason has to do with not having to worry so much about the way meteor determines what order to load files in. This was actually created by the iron:router guys and is best illustrated with an excerpt of code from the iron:router guide:

     Router.route('/post/:_id', {
      name: 'post.show',
      controller: 'CustomController'
    });

Notice how they put quotes around 'CustomController'? There's a good reason why:

Let's say CustomController inherits from ParentController. If for some reason the file which defines CustomController gets loaded before the file which defines ParentController, you will get an error and your app might even crash because it depends on a namespace which is not yet defined, even though we only need it to be defined when we actually navigate somewhere that depends on that controller. By using strings, we avoid that issue since Obj.property and Obj['property']give us the same thing.

The 2nd reason you'd want to use it has to do with minification. If you are depending on something to be called Application and meteor minifies it to _a that could get annoying, and making it a string just guarantees that it will stay that way.

I've also seen people use it as a way to make namespaces in meteor feel more like using require() in node. A quick example off the top of my head:

// Imports
var ns = App.utils.namespace;
var view = ns('Module.templates.myCoolTemplate'); 
var collection = ns('Module.collections.myCollection');

// Stuff
_.extend( view, {

  initState: function() {
    this.activeState = new ReactiveVar(null);
    this.timesClicked = new ReactiveVar(0);
  },

  incrementClicks: function() {
    this.timesClicked.set( this.timesClicked.get() + 1 );
  },  

  handleClickEvent: function(event, template) {
    event.preventDefault();
    this.incrementClicks();
   },

   isActive: function() {
     return this.activeState.get();
   },

   toggleActiveState: function() {
      this.activeState.set( ! this.activeState.get() );
    }

});

view.onCreated( this.initState );

view.onRendered(function() {
  this.autorun( this.toggleActiveState );
});

view.events({
  'click .button': this.handleClickEvent
});

view.helpers({
  isActive: view.isActive.bind(this);
});

_.extend( collection, ....
// Define new stuff or properties using var to not pollute local namespace..

// Exports
ns('App.views.newThing', newThing)
ns('App.utils.newUtil', newUtil);

So as you can see in this 3rd example it's just used to allow one to write in a way they are more comfortable with or that they feel is more organised (imports on top and exports on bottom is a pretty common pattern in node).

About implementing a sample module - I will do that soon. Keep in mind that I extracted this from a personal project so there's a bunch of stuff I still need to clean out that really has no purpose for being in the package other than the fact that I forgot to remove it haha.